반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- IAT Hooking
- 네트워크 바이트 오더
- arudino
- 포너블
- 해킹
- pwnable
- 윈도우 커널
- pcap packet
- ucrtbase.dll
- HackCTF
- packet capture
- 바이트 오더
- 개발 환경 준비
- Windows Kernel Driver
- 개발하기
- Msvcrt.dll
- apphelp.dll
- C언어 패킷캡쳐
- Windows Kernel
- 윈도우 커널 드라이버
- 윈도우 커널 디버깅
- pcap packet capture
- hacking
- windows kernel debugging
- Windows
- 시스템해킹
- Windows Kernel Debug
- vcruntime140.dll
- vcruntime.dll
- Network Byte Order
Archives
- Today
- Total
미친해커
[Reversing] Code Injection Step 2 본문
반응형
해당 포스팅은 이전 포스팅에서 이어집니다.
Why did the error occur?
에러가 발생되는 원인은 다음과 같다.
주입된 어셈블리(코드)를 확인해보면 0x1E54A422AB0를 첫번째 인자로 넘기고 0x1E54A426D8C에서 WinExec의 주소를 rax로 가져와 call 하게 된다. 하지만 해당 2개의 주소는 존재하지(사용되지) 않는 것을 확인할 수 있다.
0x1E54A422AB0는 "calc.exe" 문자열을 가르킨다. 그리고 0x1E54A426D8C에는 WinExec의 주소가 들어있다. 하지만 타겟 프로세스의 공간에는 해당 문자열("calc.exe")과 IAT(WinExec의 주소)가 존재하지 않는다. 따라서 우리는 타겟 프로세스에 인자로 들어가는 문자열(실행시킬 프로그램 이름)과 WinExec의 주소를 전달해줘야한다.
소스코드 수정
typedef UINT (*WINAPI WINEXEC)(LPCSTR, UINT);
typedef struct _INJECT_DATA
{
WINEXEC pWinExec; // WinExec 함수의 주소를 담을 함수 포인터
char string[12]; // 실행시킬 프로그램 이름
} INJECT_DATA;
// 인자의 유형을 INJECT_DATA의 포인터로 변경
DWORD WINAPI ThreadProc(INJECT_DATA *lpParameter)
{
lpParameter->pWinExec(lpParameter->string, SW_SHOW);
// WinExec("calc.exe", SW_SHOW);
}
BOOL CodeInjection(DWORD PID)
{
// 타겟 프로세스의 핸들 획득
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL)
{
printf("OpenProcess Failed!\n");
return FALSE;
}
// 주입할 함수의 사이즈를 계산
SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;
// 타겟 프로세스에 공간 할당
PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
PVOID InjectDataAddress = VirtualAllocEx(hProcess, NULL, sizeof(INJECT_DATA), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// 할당된 공간에 ThreadProc 함수 작성
if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
{
printf("WriteProcessMemory Failed!\n");
return FALSE;
}
// 구조체 생성
INJECT_DATA InjectData;
// WinExec API는 Kernel32.dll에 존재한다. GetProcAddress와 GetModuleHandle API를 이용하여 함수의 주소를 알아낼 수 있다.
InjectData.pWinExec = (WINEXEC)GetProcAddress(GetModuleHandleA("kernel32.dll"), "WinExec");
// INJECT_DATA 구조체의 string에 실행시킬 파일의 문자열을 입력한다.
strcpy(InjectData.string, "calc.exe");
// 할당된 공간에 InjectData 작성
if (WriteProcessMemory(hProcess, InjectDataAddress, (LPCVOID)&InjectData, sizeof(INJECT_DATA), NULL) == FALSE)
{
printf("WriteProcessMemory Failed!\n");
return FALSE;
}
// 쓰레드 생성 및 실행
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, (LPVOID)InjectDataAddress, 0, NULL);
if (hThread == NULL)
{
printf("CreateRemoteThread Failed\n");
return FALSE;
}
printf("Code Injection Success!\n");
return TRUE;
}
완성된 코드
#include <stdio.h>
#include <windows.h>
typedef UINT (*WINAPI WINEXEC)(LPCSTR, UINT);
typedef struct _INJECT_DATA
{
WINEXEC pWinExec;
char string[12];
} INJECT_DATA;
// 인자의 유형을 INJECT_DATA의 포인터로 변경
DWORD WINAPI ThreadProc(INJECT_DATA *lpParameter)
{
lpParameter->pWinExec(lpParameter->string, SW_SHOW);
// WinExec("calc.exe", SW_SHOW);
}
int AtherFunc() {}
BOOL CodeInjection(DWORD PID)
{
// 타겟 프로세스의 핸들 획득
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL)
{
printf("OpenProcess Failed!\n");
return FALSE;
}
// 주입할 함수의 사이즈를 계산
SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;
// 타겟 프로세스에 공간 할당
PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
PVOID InjectDataAddress = VirtualAllocEx(hProcess, NULL, sizeof(INJECT_DATA), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// 할당된 공간에 ThreadProc 함수 작성
if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
{
printf("WriteProcessMemory Failed!\n");
return FALSE;
}
// 인자로 전달할 데이터 셋팅
INJECT_DATA InjectData;
InjectData.pWinExec = (WINEXEC)GetProcAddress(GetModuleHandleA("kernel32.dll"), "WinExec");
strcpy(InjectData.string, "calc.exe");
// 할당된 공간에 InjectData 작성
if (WriteProcessMemory(hProcess, InjectDataAddress, (LPCVOID)&InjectData, sizeof(INJECT_DATA), NULL) == FALSE)
{
printf("WriteProcessMemory Failed!\n");
return FALSE;
}
// 쓰레드 생성 및 실행
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, (LPVOID)InjectDataAddress, 0, NULL);
if (hThread == NULL)
{
printf("CreateRemoteThread Failed\n");
return FALSE;
}
printf("Code Injection Success!\n");
return TRUE;
}
int main(int argc, char *argv[])
{
DWORD PID = 0;
printf("PID : ");
scanf("%d", &PID);
CodeInjection(PID);
}
빌드 후에 프로그램을 실행해 타겟 프로세스의 PID를 입력한다. 그럼 정상적으로 계산기 프로그램이 실행되는 것을 확인할 수 있다.
반응형
'Reversing > Code Injection' 카테고리의 다른 글
[Reversing] Code Injection Step 1 (0) | 2022.04.05 |
---|---|
[Reversing] Code Injection Step 0 (0) | 2022.04.04 |
Comments