首页
社区
课程
招聘
[原创][第一阶段◇第一题答案]看雪论坛.腾讯公司2008软件安全竞赛
2008-10-1 18:08 2250

[原创][第一阶段◇第一题答案]看雪论坛.腾讯公司2008软件安全竞赛

2008-10-1 18:08
2250
收藏
点赞0
打赏
分享
最新回复 (7)
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
mstwugui 6 2008-10-1 20:13
2
0
之前看错条件了,只注意到大小,误以为是文件大小, 重新上传一个版本
上传的附件:
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
mstwugui 6 2008-10-1 22:16
3
0
提交第一个版本时因为没有仔细看评分条件, 所以最初是考虑感染型修改, 尽可能少的修改原始文件, 因此除了添加一个EAT之外所有的代码和数据都存放在text段内未使用的空间里而且代码还包括定位KERNEL32的基地址,寻找GetProcAddress,加载SHELL32.DLL及ShellExecuteA并运行之, 但这样一来的结果是整个函数变得非常臃肿... :(

因此又重新做了一次

此时为了尽可能精简OpenUrlA函数, 考虑了以下几个问题

最后的函数调用肯定是不能像第一个版本那样再自己查找了, 所以对IAT的修改在所难免. 我们需要加入一个函数, 因此第一步先将Import Directory向后移动8个字节并重新构造, 在Import Directory Terminator之前插入一条新的Entry用以加载WinExec, 这里我重复利用了第一条Entry中的KERNEL32.DLL字符串

IAT修改完成后下一个目标是EAT, 因为这个DLL本身没有EAT, 所以需要构造一个新的EAT, 基本上就接着IAT写下去, 但我在IAT和EAT之间还插入了WinExec需要执行的命令字符串"explorer.exe http://bbs.pediy.com", 暂时先跳过这点后面会讨论到, EAT构造完成后将导出函数OpenUrlA指向text段末尾没有用到的地址4010EB(这里本来可以指向4010CA, 但刚开始因为一些其他考虑在4010CA写了WinExe需要执行的命令字符串, 而且后来也忘记删除了)

现在已经可以执行OpenUrlA函数了, 但为了让OpenUrlA函数尽可能简短, 显然用ShellExecuteA已经不合适了, 因为它的需要的参数太多, 因此换成WinExec, 调用"explorer.exe http://bbs.pediy.com"开启连接, 这里也算是偷了个懒, explorer.exe的路径无须指定, 系统会自动寻找, 并且explorer.exe会自动调用浏缆器开启网页, 这里最简单的做法显然是

6A 01              push    01
68 D7 20 40 00     push    offset "explorer.exe http://bbs.pediy.com"
FF 15 14 20 40 00  call    WinExec
C3                 retn

但上面这种做法函数长度是2+5+6+1=14个字节

怎样才能更精简呢? 显然push 01和retn是不可能精简的, 但注意到中间的两条指令都用了绝对地址非常浪费长度, 因此肯定是要拿他们动手了, 改成如下代码

6A 01              push    01
B8 D7 20 40 00     mov     eax, offset "explorer.exe http://bbs.pediy.com"
50                 push    eax
2C C3              sub     al, 0C3h
FF 10              call    dword ptr [eax]
C3                 retn

这里的考虑是尽量避免使用绝对地址, mov指令和后面一条push eax很容易理解, 之后再把al减了0C3h, 为什么是AL而不是EAX, 因为减EAX的话至少需要3个字节. 这就是为什么我把字符串"explorer.exe http://bbs.pediy.com"放在IAT之后的原因, 这样一来EAX的值将会变成402014h, 随后再用两个字节call dword ptr [eax]调用WinExe, 最后C3返回, 现在长度是2+5+1+2+2+1=13个字节

大功告成? 呵呵, 还差一步, 因为ImageBase是400000h, 这个地址多半已经被其他模块占用了, 因此还需要修改reloc表, 再最后添加一条记录30EE用于修改mov这条指令所用到的绝对地址

最后, XP上测试正常, 因为手边没有2000也就不测试了
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
kangaroo 6 2008-10-2 01:04
4
0
RVA:10EB
OpenUrlA函数大小=13 字节
附件提交次数=2
得分=min[1.0,(13/13)]×100-(2-1)×5=95.0

提交2次

没修改文件大小,没添加节一共加5分,最终得分100分
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
mstwugui 6 2008-10-2 04:17
5
0
12个字节就够了, 只不过因为IAT大了点, 如果要实现12个字节需要把WinExec的命令参数字符串改到IAT前面, 那样可以把代码改成

6A 01                  push      01
B8 ?? ?? ?? ??         mov       eax, offset "explorer.exe http://bbs.pediy.com"
50                     push      eax
FF 50 ??               call      dword ptr [eax+??]
C3                     retn

2+5+1+3+1 = 12个字节, 只不过按照评分条件这个改动也没有意义了
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
kangaroo 6 2008-10-2 16:27
6
0
感谢提醒,结果已修正
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
mstwugui 6 2008-10-3 18:05
7
0
不考虑min的约束, 继续琢磨一下不同的精简办法

先是考虑回跳并重复利用原来的字节,函数入口401104

401100  59                                pop     ecx
401101  51                                push    ecx
401102  FF 51 6A                       call    dword ptr [ecx+6Ah]
401105  C3                                retn
401106  E8 F5 FF FF FF              call    loc_401100
40110B  65 78 70 6C 6F 72+aExplorer_exe_0 db 'explorer.exe http://bbs.pediy.com',0

这样实际上是执行了
6A C3                      push       0FFFFFFC3h                     ; 随便压入一个值, 只要不是0 SW_HIDE就好
E8 F5 FF FF FF         call          $-6
59                           pop         ecx
51                           push       ecx                                   ; 将命令行压入堆栈
FF 51 6A                 call          dword ptr [ecx+6Ah]        ; 调用WinExec
C3                          retn

但代码长度是40110B-401100, 总共11个字节

还是不理想,继续尝试其他途径, 考虑到GetProcAddress的返回值在EAX中, 只要是动态调用如果随后直接调用OpenUrlA, 那EAX多半等于EIP

所以。。。
50                          push     eax                                  ; 还是随便压入一个不为0的参数
FF 70 10                push      dword ptr [eax+10]        ; 压入命令行参数
FF 60 10                jmp         dword ptr [eax+20]       ; 直接jmp到WinExec而不是call, 这样节约了retn

1+3+3=7

这题虽然看起来比较简单,但深入思考还是挺好玩的
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
mstwugui 6 2008-10-4 21:32
8
0
jmp不能用,先后顺序想错了,还是要call+ret, :(
另外没有想到还有ShellExecuteExA和system, 又多浪费了一个字节,呵呵
游客
登录 | 注册 方可回帖
返回