能力值:
( LV4,RANK:50 )
2 楼
//:::jmp指令地址
dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr) ;
//:::Jmp指令在内存的虚拟地址VA
dwJmpVA = (DWORD)dwJmpAddr-
((DWORD)pMapping+pImageSectionHeader->PointerToRawData)+
pImageNtHeaders->OptionalHeader.ImageBase+
pImageNtHeaders->OptionalHeader.AddressOfEntryPoint ;
//:::取jmp操作数,返回的时候使用
dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2)) ;
这儿不大懂,有朋友能指教一下吗?每次调试到dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2)) ;就出错啊,非法访问内存 dwJmpAddr+2指向什么呢?
能力值:
(RANK:570 )
3 楼
难懂的代码。。。知道原理还不如自己写来得明白
当然,知道原理也能自己搞定调试的错误,楼上显然不知道EPO的实现是基于高级语言编译器生成的代码特征和PE文件的一些特性。
我比较有兴趣知道,假如有人用变形技术和入口点模糊技术把病毒写出来了,然后当成可疑文件上报给各大杀软厂商,有多少个杀软能搞定。
能力值:
( LV4,RANK:50 )
4 楼
楼上显然不知道EPO的实现是基于高级语言编译器生成的代码特征和PE文件的一些特性 这句我不大赞成阿,原理还是大概知道的 再学习学习自己写个
能力值:
(RANK:570 )
5 楼
原理就是以代码特征,在代码段里面识别一条完整的指令,除了
PUSH EBP
MOV EBP,ESP
(高级语言编译器的特征之一,没研究过,不知道还有没有其他的)
还有
mov eax, dword ptr fs:[0]
push eax
mov dword ptr fs:[0], esp(WINDOWS的系统特性,SEH的安装)
注意mov dword ptr fs:[0], esp,有一个prefix,一个opcode,一个mod r\m byte和4个0,即是长度为7的指令。误识别率已经很低了。
而楼主代码利用的是PE的特性。
call iat
jmp iat
iat是指向对应函数地址的指针
例如00041000 xxxxxxxx(xxxxxxxx就是某个API的地址)
那么你可以看到
ff 25 00041000
或者
ff 15 00041000
好吧,现在你告诉我找到call和jmp之后,+2的是什么?
所谓的jmp data又是什么?
能力值:
( LV9,RANK:210 )
6 楼
赞一个,楼主写的这个很精秒,典型的inline hook,还用到了自定位,注入
我是这样理解的,假设hello.exe映射到内存是
.call <——dwCallDataAddr ....
. xx .
. xx .
. xx .
. xx
.push <——dwCallNextAddr .
. xx . ......................
call
xx
..
..
dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr)
dwJmpAddr指向[call xx xx xx xx push xx]中的call的地址
dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2))
之后的dwJmpData = [xx xx xx xx push xx],把这个地址放到thunk code中的jmp后,以便返回
这里的call+push指令刚好与far jump的字节数相等,都七字节。
楼主只是演示,如果实际运用,不同编译情况下,不同的OEP,第一加第二指令与far jump指令的字节数不等的话,就不会注入成功了
能力值:
( LV9,RANK:210 )
7 楼
注入前:
注入后:
上传的附件:
能力值:
( LV4,RANK:50 )
8 楼
谢楼上几位点拨
替换第一个发现的call api的指令
出现第一个0xE8时但不是call API而是其他的call岂不很容易出错?
楼主只是演示,如果实际运用,不同编译情况下,不同的OEP,第一加第二指令与far jump指令的字节数不等的话,就不会注入成功了
学习
能力值:
( LV4,RANK:50 )
9 楼
终于实验成功了,感谢作者和关注者的指点 hFile = CreateFile(szHostFile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL) ;
if (hFile==INVALID_HANDLE_VALUE)
{
printf("Open host file failed!\n") ;
return -1 ;
}
hMap = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL) ;
if (!hMap)
{
printf("Create file mapping falied!\n") ;
return -1 ;
}
pMapping = MapViewOfFile(hMap,
FILE_MAP_ALL_ACCESS,
0,
0,
0) ;
if (!pMapping)
{
printf("Map view of file failed!\n") ;
return -1 ;
}
能力值:
(RANK:1010 )
10 楼
计算空隙大小的部分有点出入
空闲大小 = 下一区块文件起始地址 - 本区块文件起始地址 - 本区块SizeOfRawData
最后尽量把VirtualSize调成最大,很多情况下,并没有Alignment
能力值:
( LV6,RANK:90 )
11 楼
嘿嘿,的确这个地方还有一个问题就是空隙的大小计算应该是有符号的,我搞成无符号的了
能力值:
( LV6,RANK:90 )
12 楼
只靠E8就判定这个是CALL指令有点危险,要好的EPO还是需要带个反汇编模块,
不知道LZ有没进行大规模的测试?
能力值:
( LV6,RANK:90 )
13 楼
所以是简单的EPO
能力值:
( LV8,RANK:130 )
14 楼
好像没有用啊!
这一句容易出现异常,加个异常处理会比较好吧
能力值:
( LV2,RANK:10 )
15 楼
没想到这个壳这么难脱。。。
能力值:
( LV2,RANK:10 )
16 楼
恩,版主的这个方法不错