很有趣<img src=
"/view/img/face/50.gif"
width=
"24"
height=
"24"
style=
"cursor: zoom-in;"
>
/*
Coder: dummyz@126.com
*/
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;
}