2012年6月30日土曜日

アナライジング・マルウェア mypacker.c サンプルコード

初投稿は現在読み進めている「アナライジング・マルウェア」(オライリー・ジャパン)のテストコードについて。

第2章のmypacker.cを作成してみたもののどうやら展開時にエントリーアドレスを取得する方法が無いと展開して実行できないみたいだ。
jmp,call,popを追加してアドレスを取得して展開領域を特定すれば良さそうだけど、
時間をかけずに次に進むことにする。
そのうち気が向いたら修正する。

とりあえず、作成したコードは以下に添付する。


#include <Windows.h>

//Data Declaration
unsigned char decode_stub[] = {
0x60, //pushad
0xBE,0xFF,0xFF,0xFF,0xFF, //mov esi, decode_start
0xB9,0xFF,0xFF,0xFF,0xFF, //mov ecx, decode_size
0x81,0xC6,0xFF,0xFF,0xFF,0xFF, //add esi, base_addr
0xB0,0xFF, //mov al, decoder
0x30,0x06, //xor byte ptr [esi], al(loop)
0x46, //inc esi
0x49, //dec ecx
0x75,0xFA, //jnz loop
0x61, //popad
0xE9,0xFF,0xFF,0xFF,0xFF //jmp oep
};

unsigned int decode_start_offset = 2;
unsigned int decode_size_offset = 7;
unsigned int base_address_offset =13;
unsigned int decoder_offset =18;
unsigned int jmp_oep_addr_offset =27;

//Function Declaration
void create_decode_stub(
unsigned int code_vaddr, unsigned int code_vsize,
unsigned int base_addr, BYTE decoder, unsigned int oep
){
int cnt=0;
int jmp_len_to_oep=0;

jmp_len_to_oep = oep - (code_vaddr + code_vsize + sizeof(decode_stub));

memcpy(&decode_stub[decode_start_offset],&code_vaddr,sizeof(DWORD));
memcpy(&decode_stub[decode_size_offset],&code_vsize,sizeof(DWORD));
memcpy(&decode_stub[base_address_offset],&base_addr,sizeof(DWORD));
memcpy(&decode_stub[decoder_offset],&decoder,sizeof(BYTE));
memcpy(&decode_stub[jmp_oep_addr_offset],&jmp_len_to_oep,sizeof(DWORD));
return;
}

void xor_encoder(unsigned char *start, unsigned int size, BYTE encoder){
unsigned int cnt=0;
for(cnt=0;cnt<size;cnt++){
start[cnt] ^= encoder;
}
return;
}

struct _IMAGE_NT_HEADERS* get_nt_header(LPVOID lpTargetBinBuffer){
LPVOID *nt_header;
struct _IMAGE_DOS_HEADER *dos_header = (struct _IMAGE_DOS_HEADER*)lpTargetBinBuffer;
nt_header = (LPVOID*)dos_header + dos_header->e_lfanew / 4;
return (struct _IMAGE_NT_HEADERS*)nt_header;
}

struct _IMAGE_SECTION_HEADER* search_oep_include_section_header( struct _IMAGE_NT_HEADERS *nt_header,
unsigned int oep){
unsigned int number_of_section;
unsigned int i;
unsigned int section_start,section_end;
struct _IMAGE_SECTION_HEADER *section_header, *result;
struct _IMAGE_OPTIONAL_HEADER *o_header;
o_header = (struct _IMAGE_OPTIONAL_HEADER*)((unsigned int)nt_header + 24);
result = NULL;

number_of_section = nt_header->FileHeader.NumberOfSections;
for(i=0;i<number_of_section;i++){
section_header = (struct _IMAGE_SECTION_HEADER*)((unsigned int)o_header + nt_header->FileHeader.SizeOfOptionalHeader + sizeof(struct _IMAGE_SECTION_HEADER) * i);
section_start = section_header->VirtualAddress - section_header->PointerToRawData;
section_end = section_start + section_header->SizeOfRawData;
if((section_start <= oep) && (section_end > oep)){
result = section_header;
break;
}
}
return result;
}

int main(int argc, char **argv){
char* target_filename;
char* packed_filename;
HANDLE hTargetBin,hPackedBin;
DWORD dwTargetBinSize;
DWORD dwReadSize,dwWriteSize;
LPVOID lpTargetBinBuffer;
BOOL bRslt;
struct _IMAGE_NT_HEADERS *nt_header;
DWORD oep;
DWORD base_addr;
struct _IMAGE_SECTION_HEADER *oep_section_header;
unsigned int section_vaddr,section_vsize,section_raddr,section_rsize;
char encoder = 0xFF;
BOOL ret;

target_filename = argv[1];
packed_filename = argv[2];

//Read target file.
hTargetBin = CreateFile(target_filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
if(hTargetBin == INVALID_HANDLE_VALUE){
ret = FALSE;
goto END;
}

dwTargetBinSize = GetFileSize(hTargetBin, NULL);
if(dwTargetBinSize == -1){
ret = FALSE;
goto END;
}

lpTargetBinBuffer = (unsigned char*)malloc(sizeof(unsigned char) * dwTargetBinSize);
if(lpTargetBinBuffer == NULL){
ret = FALSE;
goto END;
}

bRslt = ReadFile(hTargetBin, lpTargetBinBuffer, dwTargetBinSize, &dwReadSize, NULL);
if(!bRslt && dwTargetBinSize != dwReadSize){
ret = FALSE;
goto END;
}
//get PE header information
nt_header = get_nt_header(lpTargetBinBuffer);
oep = nt_header->OptionalHeader.AddressOfEntryPoint;
base_addr = nt_header->OptionalHeader.ImageBase;
//get code section offset
oep_section_header = search_oep_include_section_header(nt_header, oep);
if(oep_section_header == NULL){
ret = FALSE;
goto END;
};
section_vaddr = oep_section_header->VirtualAddress;
section_vsize = oep_section_header->Misc.VirtualSize;
section_raddr = oep_section_header->PointerToRawData;
section_rsize = oep_section_header->SizeOfRawData;

//encoding
xor_encoder(
(unsigned char*)(oep_section_header->PointerToRawData + (unsigned int)lpTargetBinBuffer),
oep_section_header->Misc.VirtualSize,
encoder);

//crete decode stub
create_decode_stub(section_vaddr, section_vsize,base_addr,encoder,oep);
//add decode stub
memcpy((unsigned char*)(section_raddr + section_vsize + (unsigned int)lpTargetBinBuffer),decode_stub,sizeof(decode_stub));

//amend PE header
//enlarge code section
oep_section_header->Misc.VirtualSize = section_rsize;
//amend entry point
nt_header->OptionalHeader.AddressOfEntryPoint = section_vaddr + section_vsize;
//add write property to code section
oep_section_header->Characteristics |= IMAGE_SCN_MEM_WRITE;

//write packed program
hPackedBin = CreateFile(packed_filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hPackedBin == INVALID_HANDLE_VALUE){
ret = FALSE;
goto END;
}

bRslt = WriteFile(hPackedBin,lpTargetBinBuffer,dwTargetBinSize,&dwWriteSize,NULL);
if(!bRslt && dwTargetBinSize != dwWriteSize){
ret = FALSE;
goto END;
}

ret = TRUE;

END:
if(hTargetBin!=INVALID_HANDLE_VALUE){
CloseHandle(hTargetBin);
}
if(hPackedBin!=INVALID_HANDLE_VALUE){
CloseHandle(hPackedBin);
}
if(lpTargetBinBuffer){
free(lpTargetBinBuffer);
lpTargetBinBuffer = NULL;
}
return ret;
}

0 件のコメント:

コメントを投稿