没有做各种错误处理和异常处理,以及如果失败需要还原属性
一个简单的例子
1.新增一个节用于解密代码段, 写入解密字节码,用于还原代码段
2.找到入口所在的代码段,加密
3.修改入口点指向新增节,修改.text属性加上可写
执行流程, 新节->解密还原代码段->跳转代码段
使用的exe是:win32asm 自定义PE头
由于exe使用的文件对齐是0x1000,下面代码中虽然写了512字节.经过函数计算还是会使用4096字节
解密汇编:
00405000 > 60 pushad
00405001 BE 00104000 mov esi,0x401000
00405006 B9 00100000 mov ecx,0x1000
0040500B 8036 CC xor byte ptr ds:[esi],0xCC
0040500E 46 inc esi
0040500F ^ E2 FA loopd short 0040500B
00405011 61 popad
00405012 BB 00104000 mov ebx,0x401000
00405017 - FFE3 jmp ebx
00405019 90 nop
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <iostream>
using std::cout;
using std::endl;
IMAGE_SECTION_HEADER * find_section(void * mem, DWORD rva) {
IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER *)mem;
IMAGE_NT_HEADERS * nt = (IMAGE_NT_HEADERS*)((DWORD)dos + dos->e_lfanew);
int n = nt->FileHeader.NumberOfSections;
IMAGE_SECTION_HEADER * sec = 0;
IMAGE_SECTION_HEADER * header = IMAGE_FIRST_SECTION(nt);
for (int i = 0; i < n; ++i) {
if (rva >= header->VirtualAddress && rva < header->VirtualAddress + header->SizeOfRawData) {
sec = header;
break;
}
header++;
}
return sec;
}
DWORD calc_mem_section_size(void * mem,DWORD raw_size) {
IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER*)mem;
IMAGE_NT_HEADERS * nt = (IMAGE_NT_HEADERS *)((DWORD)dos + dos->e_lfanew);
DWORD new_section_size = 0;
if (raw_size <= nt->OptionalHeader.SectionAlignment)
new_section_size = nt->OptionalHeader.SectionAlignment;
else {
new_section_size = raw_size / nt->OptionalHeader.SectionAlignment * nt->OptionalHeader.SectionAlignment;
if (raw_size % nt->OptionalHeader.SectionAlignment != 0)
new_section_size += nt->OptionalHeader.SectionAlignment;
}
return new_section_size;
}
DWORD calc_file_section_size(void * mem, DWORD raw_size) {
IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER*)mem;
IMAGE_NT_HEADERS * nt = (IMAGE_NT_HEADERS *)((DWORD)dos + dos->e_lfanew);
DWORD new_section_size = 0;
if (raw_size <= nt->OptionalHeader.FileAlignment)
new_section_size = nt->OptionalHeader.FileAlignment;
else {
new_section_size = raw_size / nt->OptionalHeader.FileAlignment * nt->OptionalHeader.FileAlignment;
if (raw_size % nt->OptionalHeader.FileAlignment != 0)
new_section_size += nt->OptionalHeader.FileAlignment;
}
return new_section_size;
}
DWORD add_section(void * mem, const char * section_name, DWORD raw_section_size,DWORD mode) {
IMAGE_SECTION_HEADER * new_section = 0;
__try {
IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER*)mem;
IMAGE_NT_HEADERS * nt = (IMAGE_NT_HEADERS *)((DWORD)dos + dos->e_lfanew);
IMAGE_SECTION_HEADER * sec = IMAGE_FIRST_SECTION(nt);
WORD n_sections = nt->FileHeader.NumberOfSections;
// 构建一个节
new_section = (IMAGE_SECTION_HEADER*)((DWORD)sec + n_sections * sizeof(IMAGE_SECTION_HEADER));
IMAGE_SECTION_HEADER * last_section = (IMAGE_SECTION_HEADER*)((DWORD)sec + (n_sections - 1) * sizeof(IMAGE_SECTION_HEADER));
strcpy((char*)new_section->Name, section_name);
new_section->Misc.VirtualSize = raw_section_size;//真实字节,未对齐
DWORD last_section_size = calc_mem_section_size(mem, last_section->SizeOfRawData);// 内存对齐字节
DWORD new_section_size = calc_mem_section_size(mem, raw_section_size);
DWORD new_raw_section_size = calc_file_section_size(mem, raw_section_size);
new_section->VirtualAddress = last_section->VirtualAddress + last_section_size;
new_section->SizeOfRawData = new_raw_section_size;
new_section->PointerToRawData = last_section->PointerToRawData + last_section->SizeOfRawData;
new_section->Characteristics = mode;
// 修改节数量,增加映像大小
++nt->FileHeader.NumberOfSections;
nt->OptionalHeader.SizeOfImage += new_section_size;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
return 0;
}
return (DWORD)new_section;
}
void encrypt_source_code(void * source_code,DWORD size) {
//简易加密,直接异或CC
unsigned char ecode = 0xCC;
unsigned char * source_begin = (unsigned char *)source_code;
for (DWORD i = 0; i < size; ++i) {
*source_begin++ ^= ecode;
}
}
bool encrypt_code_segment(void * mem,HANDLE hFile) {
//以下代码并未考虑异常以及如果失败了需要还原属性
//找到代码段所属的节
char write_bin_unpack_code[] = { 0x60,0xBE,0x00,0x10,0x40,0x00,0xB9,0x00,0x10,0x00,0x00,0x80,0x36,0xCC,0x46,0xE2,0xFA,0x61,0xBB,0x00,0x10,0x40,0x00,0xFF,0xE3,0x90 };
IMAGE_DOS_HEADER * dos = (IMAGE_DOS_HEADER *)mem;
IMAGE_NT_HEADERS * nt = (IMAGE_NT_HEADERS *)((DWORD)dos + dos->e_lfanew);
DWORD ep = nt->OptionalHeader.AddressOfEntryPoint;//入口点
IMAGE_SECTION_HEADER * sec = find_section(mem, ep);
if (0 == sec)
return false;
sec->Characteristics |= IMAGE_SCN_MEM_WRITE;//修改代码段属性
void * source_code = (void*)((DWORD)mem+ sec->PointerToRawData);
//加密
encrypt_source_code(source_code, sec->SizeOfRawData);
//新增一个节
char new_sec_name[] = ".unpack"; // 名字
DWORD mode = 0xE0000040; // 属性
DWORD nWritten = 0;
DWORD new_sec_size = 512; //新节大小,实际根据函数计算得出
unsigned char other_bin = 0xCC;
IMAGE_SECTION_HEADER * new_sec = (IMAGE_SECTION_HEADER*)add_section(mem, new_sec_name, new_sec_size, mode);
if (0 == new_sec)
return false;
SetFilePointer(hFile, new_sec->PointerToRawData, 0, FILE_BEGIN);
WriteFile(hFile, write_bin_unpack_code, sizeof(write_bin_unpack_code), &nWritten, 0);
int iLeftSize = new_sec->SizeOfRawData - nWritten;
void * pmem = malloc(iLeftSize);
unsigned char * pdata = (unsigned char *)pmem;
for (int i = 0; i < iLeftSize; ++i) {
*pdata++ = other_bin;
}
WriteFile(hFile, pmem, iLeftSize, &nWritten, 0);
nt->OptionalHeader.AddressOfEntryPoint = new_sec->VirtualAddress; // 修改入口点
free(pmem);
return true;
}
void encrypt__(TCHAR * filename) {
HANDLE hFileHandle = 0;
HANDLE hMap = 0;
void * mem = 0;
DWORD err = 0;
__try {
hFileHandle = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (INVALID_HANDLE_VALUE == hFileHandle) {
err = 1;
__leave;
}
hMap = CreateFileMapping(hFileHandle, 0, PAGE_READWRITE, 0, 0, 0);
if (0 == hMap) {
err = 2;
__leave;
}
mem = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (0 == mem) {
err = 3;
__leave;
}
if (!encrypt_code_segment(mem, hFileHandle)) {
err = 4;
__leave;
}
}
__finally {
UnmapViewOfFile(mem);
CloseHandle(hMap);
CloseHandle(hFileHandle);
if (err != 0) {
cout << err << endl;
}
}
}