win32asm 自定义代码段加密解密

没有做各种错误处理和异常处理,以及如果失败需要还原属性

一个简单的例子

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;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值