首页
社区
课程
招聘
[原创]未知壳乱序重构
发表于: 2008-1-15 19:44 7379

[原创]未知壳乱序重构

dummy 活跃值
23
2008-1-15 19:44
7379
很有趣 
/*
Coder: dummyz@126.com
*/

#include <Windows.h>
#include <fstream>
#include <memory>
#include <list>
#include <algorithm>
#include "xde.h"

using namespace std;

typedef unsigned char ubyte;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

ubyte* load_pefile(const char* fname, ulong& size)
{
	IMAGE_DOS_HEADER dosheader;
	IMAGE_NT_HEADERS ntheader;
	ifstream ifile(fname, ios::binary);

	if ( !ifile )
		return NULL;

	ifile.read((char*)&dosheader, sizeof (IMAGE_DOS_HEADER));
	if ( dosheader.e_magic != IMAGE_DOS_SIGNATURE )
		return NULL;

	ifile.seekg(dosheader.e_lfanew, ios::beg);

	ifile.read((char*)&ntheader, sizeof (IMAGE_NT_HEADERS));
	if ( ntheader.Signature != IMAGE_NT_SIGNATURE || 
		ntheader.FileHeader.NumberOfSections == 0 )
		return NULL;

	size = ifile.seekg(0, ios::end).tellg();
	ifile.seekg(0, ios::beg);

	auto_ptr<ubyte> buf(new ubyte[size]);
	ifile.read((char*)buf.get(), size);

	return buf.release();
}

typedef struct _instr
{
	ubyte* old_ip;
	ubyte* new_ip;
	xde_instr instr;
} instr_t;

bool is_hasip(list<instr_t>& instr_lst, ubyte* ip)
{
	list<instr_t>::iterator i = instr_lst.begin();
	while ( i != instr_lst.end() )
	{
		instr_t& p = *i++;
		if ( p.old_ip == ip )
		{
			return true;
		}
	}

	return false;
}

int main(int argc, char* argv[])
{
	if ( argc < 2 )
	{
		return -1;
	}
	
	ulong file_size;
	auto_ptr<ubyte> file_buf(load_pefile(argv[1], file_size));
	ubyte* base = file_buf.get();
	if ( base == NULL )
	{
		return -2;
	}
	
	list<instr_t> instr_lst; // 指令表
	list<ubyte*> ep_list; // 入口表
	instr_t instr;

	PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)base;
	PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)(base + dosheader->e_lfanew);
	PIMAGE_SECTION_HEADER sectheader = IMAGE_FIRST_SECTION(ntheader);
	
	ulong code_size = ntheader->OptionalHeader.SizeOfCode;
	ulong code_va = ntheader->OptionalHeader.ImageBase + sectheader->VirtualAddress;
	ulong oep_va = ntheader->OptionalHeader.ImageBase + ntheader->OptionalHeader.AddressOfEntryPoint;

	ubyte* code = base + sectheader->VirtualAddress;

	instr.old_ip = base + ntheader->OptionalHeader.AddressOfEntryPoint - \
		sectheader->VirtualAddress + sectheader->PointerToRawData;
	
	auto_ptr<byte> code_buf(new byte[code_size * 2]);
	memset(code_buf.get(), 0x90, code_size * 2);

	instr.new_ip = code_buf.get() + ntheader->OptionalHeader.AddressOfEntryPoint - \
		sectheader->VirtualAddress;
	
	// @1 重构串行指令序
	ep_list.push_back(instr.old_ip);
	while ( true )
	{
		list<ubyte*>::iterator it;
		
		printf("\r\bPasering eip = %08X...", instr.old_ip - code + code_va);
		
		if (
			instr.old_ip > code + code_size ||
			is_hasip(instr_lst, instr.old_ip) // 检查是否已经处理过了, 从入口表中取出新的地址
			)
		{
			if ( ep_list.empty() )
				break;

			instr.old_ip = ep_list.front();
			ep_list.erase(ep_list.begin());
		}

		if ( 0 == xde_disasm(instr.old_ip, &instr.instr) )
		{
			printf("xde_disasm error!\n");
			break;
		}

		/*
0040102C > $  C705 00104000>mov     dword ptr [401000], 00401333
00401036   .  FF25 00104000 jmp     dword ptr [401000]
		*/
		if ( instr.instr.opcode == 0xc7 &&
			instr.instr.modrm == 0x05 &&
			(instr.instr.addr_l[0] >= code_va && instr.instr.addr_l[0] < oep_va) 
			)
		{
			ubyte* next_ep_ip = instr.old_ip + instr.instr.len;
			if ( *(ushort*)next_ep_ip == 0x25ff &&
				*(ulong*)(next_ep_ip + 2) == instr.instr.addr_l[0] 
				)
			{
				next_ep_ip += 6;
				if ( ep_list.end() == find(ep_list.begin(), ep_list.end(), next_ep_ip) && 
					!is_hasip(instr_lst, next_ep_ip) 
					)
				{
					ep_list.push_back(next_ep_ip);
				}
				
				instr.old_ip = instr.instr.data_l[0] - code_va + code;
				continue;
			}
		}

		if ( instr.instr.flag & C_REL )
		{
			ubyte* next_ep_ip = instr.old_ip + instr.instr.len;
			switch ( instr.instr.datasize )
			{
			case 1: next_ep_ip = (ubyte*)((ulong)next_ep_ip + (long)instr.instr.data_c[0]); break;
			case 4: next_ep_ip = (ubyte*)((ulong)next_ep_ip + (long)instr.instr.data_l[0]); break;
			default: printf("error datasize!\n");	
			}

			if ( ep_list.end() == find(ep_list.begin(), ep_list.end(), next_ep_ip) && 
				!is_hasip(instr_lst, next_ep_ip) 
				)
			{
				ep_list.push_back(next_ep_ip);
			}

			if ( instr.old_ip[0] == 0x8a )
			{
				instr.old_ip[0] = 0x8a;
			}
		}
		
		it = find(ep_list.begin(), ep_list.end(), instr.old_ip);
		if ( ep_list.end() != it ) // 从入口表中踢出
		{
			ep_list.erase(it);
		}

		instr_lst.push_back(instr);
		instr.new_ip += instr.instr.len;

		if ( instr.old_ip[0] == 0xc3 ||
			instr.old_ip[0] == 0xc2 
			)
		{
			if ( ep_list.empty() )
				break;

			instr.old_ip = ep_list.front();
			ep_list.erase(ep_list.begin());
		}
		else
		{
			instr.old_ip += instr.instr.len;
		}
	}
	
	printf("\ninstr sum = %d\n", instr_lst.size());
	
	// @2 拷贝 & 校正偏移
	list<instr_t>::iterator instr_lst_i = instr_lst.begin();
	while ( instr_lst_i != instr_lst.end() )
	{
		instr_t& instr1 = *instr_lst_i++;
		
		printf("\r\bRelocing eip = %08X...", instr1.new_ip - code_buf.get() + code_va);

		if ( instr1.instr.flag & C_REL )
		{
			ubyte* jmp_ip = instr1.old_ip + instr1.instr.len;
			switch ( instr1.instr.datasize )
			{
			case 1: jmp_ip = (ubyte*)((ulong)jmp_ip + (long)instr1.instr.data_c[0]); break;
			case 4: jmp_ip = (ubyte*)((ulong)jmp_ip + (long)instr1.instr.data_l[0]); break;
			default: printf("error datasize!\n");
			}
			
			do 
			{
				if ( jmp_ip[0] == 0xc7 && jmp_ip[1] == 0x05 &&
					*(ulong*)(jmp_ip + 2) >= code_va && *(ulong*)(jmp_ip + 2) < oep_va
					)
				{
					if ( *(ushort*)(jmp_ip + 2 + 4 + 4) == 0x25ff &&
						*(ulong*)(jmp_ip + 2 + 4 + 4 + 2) == *(ulong*)(jmp_ip + 2) )
					{
						jmp_ip = *(ulong*)(jmp_ip + 2 + 4) - code_va + code;
						continue;
					}
				}

				break;
			} while( true );
			
			list<instr_t>::iterator instr_lst_j = instr_lst.begin();
			while ( instr_lst_j != instr_lst.end() )
			{
				instr_t& instr2 = *instr_lst_j;
				if ( instr2.old_ip == jmp_ip )
				{
					xde_instr tmp = instr1.instr;

					tmp.data_l[0] = instr2.new_ip - instr1.new_ip + instr1.instr.len;
					xde_asm(instr1.new_ip, &tmp); // 汇编
					break;
				}

				instr_lst_j++;
			}

			if ( instr_lst_j == instr_lst.end() )
			{
				printf("reloc jmp error!\n");
				break;
			}
		}
		else
		{
			memcpy(instr1.new_ip, instr1.old_ip, instr1.instr.len);
		}
	}
	
	ofstream ofile("1.bin", ios::binary);
	ofile.write((char*)code_buf.get(), code_size);
	
	printf("\nFinished!\n");

	return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
2
学习+膜拜
先顶,再看什么壳
2008-1-15 20:03
0
雪    币: 817
活跃值: (1927)
能力值: ( LV12,RANK:2670 )
在线值:
发帖
回帖
粉丝
3
很暴力
2008-1-16 03:32
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
4
太黄了,我赶紧把窗口关了
2008-1-16 18:55
0
雪    币: 304
活跃值: (82)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
你这样很虚伪.
ps:直接被毒霸咔嚓了。
2008-1-17 11:55
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
6
学习了~~~
2008-1-17 12:00
0
雪    币: 192
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
靠,没开杀毒,下来运行,没反应,再看中弹了,木马说一下啊
2008-1-17 16:19
0
雪    币: 272
活跃值: (143)
能力值: ( LV15,RANK:930 )
在线值:
发帖
回帖
粉丝
8

我....
2008-1-17 19:38
0
雪    币: 136
活跃值: (105)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
9
哈哈 中毒好啊 又将要有木马分析篇了
2008-1-18 20:52
0
游客
登录 | 注册 方可回帖
返回
//