首页
社区
课程
招聘
[原创]由手动变自动:魔兽争霸助手的附加(附原代码及说明)
发表于: 2010-9-17 21:09 10991

[原创]由手动变自动:魔兽争霸助手的附加(附原代码及说明)

2010-9-17 21:09
10991
  以前谈到过手动PEDIY魔兽Game.dll让warkey与其生死相依。现在的魔兽已经更新到1.24版了,但基本上我们还在用1.20e版,为啥?对战平台上还是支持1.20啊!这样就造成一个问题:看魔兽rep的时候得更改版本,看完以后呢,又得改回来!

  以前手动PEDIY的DLL得单独存放,更新以后又得再复制进去,于是本人又觉得麻烦了,能不能变手动为自动呢?答案是肯定的!然而在这期间本人也遇到了一些问题,特此留档,欢迎指教!

  我想的是比较简洁地利用节间隙的办法来插入代码,这就要求代码尽可能的短而有效。前面说过的PEDIY中的三个函数FindWindowA, SendMessageA, ShellExecuteA(此函数由WinExec代替)在代码中还是会用到,如果用SHELLCODE的办法直接插入代码到.text节间隙,很可能会空间不够用!因为必须首先要查找到三个函数的地址才能调用它,所以我还是想添加导入函数的办法来做,这样可以大大简化插入的代码空间。

  我参看了LordPE的办法,它是向PE中添加一个新节,然后将要添加的输入表等信息添加到复制来的输入表尾,并连同ThunkData、IAT的信息一起放在所添加的新节中。新节的属性是可读写执行。

  但是这样会造成Game.dll的大小再次增大,本来已经够大的,8M左右,不能让大再大下去了,所以我放弃添加新节的方法,将导入函数信息等都放在原输入表所在的节: .rdata
此节属性为只读。当我成功添加好函数的时候,发生了一个郁闷了我整整一天的问题:Game.dll不能正常启动!我想到可能是rdata节属性为只读,于是我将其属性加上了“可写”。于是Game.dll被正常载入,启动也正常了。

  大家想到这个问题了吗:同样是在.rdata节,为什么其它的IAT地址表能被正常填充,而我在此节添加的导入函数IAT却不能被写入?我百思不得其解!幸好得到了figo的帮助,虽然他没有直接回答我的问题,但却提醒了我:肯定是IAT表所在的位置有问题,但同样是在rdata区段,为什么就不能填充呢?难道非得改此节的属性吗,但我又不想轻意这样做。而且还想找到这个问题的答案。

  我思考了一个晚上,第二天在查看此dll的数据目录的时候眼前一亮,答案原来就在眼前!如下图所示,数据目录在存在一个IAT表,这里指定了IAT所在的地址与大小。分析一下其数据就能发现,这个IAT所在的位置正好在rdata的前端部分!而在这一部分的IAT表在加载的时候能够被正常填充,这说明什么?说明ExeLoader在载入此节的时候会对数据目录中的IAT表所指定的区域属性进行更改!至少会加上一个“可写”的属性。所以,我们只要将此IAT表的大小扩展到覆盖住添加的IAT所在的位置就能起到让此DLL文件正常被载入的目的。



  解决了这个问题以后,后面的事情就好办多了。由于是dll,所以可能涉及到重定位的问题,添加到rdata节段的由FirstThunk值+实际的基址值才能得到真实的函数地址。形如: call dword ptr[FirstThunk + ImageBase]。我尝试用PEB的ImageBase,但是不对!这个值是载入者进程的基址,而我想要的是此DLL的基址,这是我遇到的第二个问题:如何得到当前DLL的ImageBase值呢?

  呵呵,这个问题其实也很简单,用SDK开发过DLL的人都知道DllMain函数:
  BOOL APIENTRY DllMain( HANDLE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
  )
  {
    return TRUE;
  }

  看到没有,第一个参数就是hModule,也就是我们朝思暮想的ImageBase,这个参数在加载的时候就会被ExeLoader压入堆栈,所以想得到它也是轻而易举:
  mov eax, [esp+4] ; 这样eax值就是当前DLL的基址

  最后,为了防止多次添加,得对文件作一个标记。我选择在Dos头的e_lfanew的前一个字节作上标记:0xff,每次运行的时候检查一下,就能确定文件是否已经添加附加启动信息了。最后可以看到自动附加的代码:



  是不是比手动PEDIY的更加简洁呢?给出原码,欢迎大家指点!

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
2
http://bbs.pediy.com/showthread.php?t=82841手动PEDIY魔兽Game.dll让warkey与其生死相依
结合看才看懂楼主要说啥意思
2010-9-17 23:30
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
3
心有多大 舞台就有多大 逆向无解
2010-9-17 23:31
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
4
植物大战僵尸 和 DOTA   被PEDIY的最惨了
2010-9-17 23:32
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
5
呵呵,代码段的注入代码还能再精简,这个好像是88字节,有点大,我试了下能精简到62字节。

__start:
        __asm
        {
                pushad
                        //得到本模块的模块基址,本来是esp+4,但pushad 8*4=32字节内容,所以是36 (0x24)
                        mov eax, [esp+0x24]  
                        xchg eax, edi   
                        call lb0
                        __emit 'w'
                        __emit 'a'
                        __emit 'r'
                        __emit 'k'
                        __emit 'e'
                        __emit 'y'
                        __emit 0
lb0:
                pop esi
                        push esi   //FindWindowA(NULL, "warkey")
                        push 0
                        call [edi+0x11111111]  //FindWindowA函数地址 函数地址 = (基址+RVA(FirstThunk))
                        or eax, eax
                        jnz lb1
                        push SW_SHOWNORMAL  
                        push esi
                        call [edi+0x33333333] //WinExec函数地址
                        jmp lb3
lb1:
                push 0
                        push 0
                        push WM_CLOSE
                        push eax
                        call [edi+0x22222222]   //SendMessageA(hWnd, WM_CLOSE, NULL, NULL);
lb3:
                popad      //恢复所有寄存器,并跳往原OEP
                        __emit 0xE9
                        __emit 0x44
                        __emit 0x44
                        __emit 0x44
                        __emit 0x44
        }       
       
__End:
2010-9-17 23:52
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
6
另外输入表依靠.rdata节间隙如果采用复制的方法好像浪费比较大,如果能向后调整体挪动一点,再添加输入表就非常棒了,嘿嘿
2010-9-17 23:57
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
7
看了一下,似乎难度非常大,可能会破坏掉输出表内容和输入表的OriginFirstThunk/IAT,这些值都可能需要修正。
2010-9-18 09:00
0
雪    币: 125
活跃值: (161)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
winexec        函数的地址还是手动添加进去的么?
2010-9-18 17:50
0
雪    币: 125
活跃值: (161)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
对不起 刚没仔细看代码  看完后发现了个 AddFunc2IDT函数。
2010-9-18 18:00
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
貌似我中午的回帖被删了...
2010-9-18 18:16
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
11

进行了改进:
    1、对SHELLCODE和输入表都用间隙优先的方式进行附加。
    2、如果节间隙空间不足,再增加新节的方式进行添加代码或输入表。
    3、保持OEP处于.text节段,防止变态的卡巴大叔。
    4、增加了错误处理和类代码整理。
    5、对SHELLCODE进行了简化。

优点:
    适用于魔兽争霸的所有版本!
上传的附件:
  • g.JPG (98.57kb,531次下载)
2010-9-19 22:09
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
这个会报作弊。。。。
2010-9-20 09:18
0
雪    币: 249
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
看到魔兽呗吸引来了  

刚编译了。。 先运行看下效果
2010-9-20 23:00
0
雪    币: 126
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
没看懂,但还是顶一个
2010-9-27 10:33
0
游客
登录 | 注册 方可回帖
返回
//