首页
社区
课程
招聘
[原创]看雪论坛.腾讯公司2008软件安全竞赛 第一阶段第一题 分析报告
发表于: 2008-10-4 01:17 2940

[原创]看雪论坛.腾讯公司2008软件安全竞赛 第一阶段第一题 分析报告

2008-10-4 01:17
2940
看雪论坛.腾讯公司2008软件安全竞赛 第一阶段第一题 分析报告

使用工具 
OD(编写指令汇编码), 
VC6(调试环境, 16进制编辑DLL), 
IDA(看看DLL都做些什么),
Peditor(修改PE头格式)

一 Pediy.dll文件中各个函数的功能简述及结构
二 打开URL的调用方式
三 增加导入/导出函数
四 增加命令字符串
五 导出函数的标准方法
六 7字节导出函数方法的探讨
七 缩小文件尺寸, 节的优化

一 Pediy.dll文件中各个函数的功能简述及结构
sub_401000() 在DllEntryPoint()中调用 弹出一个提示对话框
DllEntryPoint() DllMain()的函数
sub_401062() 在进程初始化时调用 根据参数调用初始化函数
sub_40107C() 在进程初始化时调用 调用sub_4010B0()分配堆空间, 尺寸为4*0x20字节
sub_401094() 在进程退出时调用 进程退出时根据标志位dword_403050,是否调用一些函数
sub_4010B0() 根据参数从堆上分配空间

文件共有四个节
节名  内存中偏移  内存中尺寸  文件中偏移  文件中尺寸  说明
.text  0x1000  0xCA  0x400  0x200  代码
.rdata  0x2000  0xAA  0x600  0x200  导入/导出函数
.data  0x3000  0x54  0x800  0x200  数据
.reloc  0x4000  0x4C  0xA00  0x200  重定位

导入函数:
KERNEL32.DLL中 GetProcessHeap和HeapAlloc
USER32.DLL中 MessageBoxA

导出函数:无

二 打开URL的调用方式
CreateProcess(),参数太多
ShellExecute(),参数太多 不建议使用
WinExec(),两个参数,自动栈平衡, 实现14Byte
MSVCRT.DLL中system() 一个参数, 手动栈平衡, 实现13Byte
先测试一下C语言的调用
1 WinExec("cmd.exe /c \"start http://bbs.pediy.com", SW_SHOW);
对应构造的汇编码(14B)
  push 5 ; SW_SHOW ;+1B
  push offset "cmd.exe /c \"start http://bbs.pediy.com" ;+5B
  call dword ptr [__imp__WinExec@8 (0042a14c)] ; +6B ;标准API会自动栈平衡
  ret ;+1B

2 system("start http://bbs.pediy.com");
对应构造的汇编码
  push  offset "start http://bbs.pediy.com" ;5
  call dword ptr [system] ;6
  pop ecx ;1平衡栈
  ret ;1

调用的命令字符串会有所不同,
由于WinExec()命令中必须要有一个文件来启动,我就选择了cmd.exe, 
而 system() 本身就相当于启动了一个”cmd.exe”,可参见VC中CRT源文件system.c
至于”start”,它不是一个文件,而是一个内部命令,在”命令提示符”中, 输入” start /?”命令,就可以得到详细的帮助说明.

三 增加导入/导出函数
  目前即然已经有导入函数,就无需自己在启动后用代码进行导入函数,直接修改相应的表即可.具体的结构可参考MSDN中PE索引和<<加密与解密三>>第10章, 我就不在这献丑了,
下面贴出将.rdata节的修改过程
1 原始
 
2 增加导入函数MSVCRT.DLL中system()函数, 修改相应的数据目录和节的尺寸
 
  修改 .rdata节 长度0xaa ==>0x200
  修改 导入表目录 RVA=0x201C size=0x50 
  修改 导入表地址目录 RVA=0x2000 size=0x1C
system()导入函数的地址保存在[0x402014]处

3 增加导出函数, 修改相应的数据目录和节的尺寸
 
  修改 导出表目录 RVA=0x2100 size=0x45
  修改 .text节 长度0xca ==>0x100
OpenUrlA()导出函数的地址为0x 4010d0

四 增加命令字符串
   在0x402060(文件中0x460)处增加命令数据字符, 并修改 .data节 长度0x54 ==>0x80

 

五 导出函数的标准方法
采用system()的13字节标准方法
  68 43060     push  offset "start http://bbs.pediy.com" ;5
  FF 15 42014  call dword ptr [system] ;6
  59           pop ecx ;1
  c3           ret ;1
需要注意的是由于此时有两个地址(” 43060”和” 42014”),是相对的地址,也就是说当映像不在0x40000处加载时,需要对其重定位,故对重定位表也需要做一定的修改
修改重定位表 修改重定块长度为0x20 == >0x22 增加 0x10d1 0x10d7
修改 重定位目录 RVA=0x4000 size=0x22

原始

修改后
 

六 7字节导出函数方法的探讨
我的思路是在数据节中已构造好一个模拟栈,再将栈复制到堆中,到时OpenUrlA()只需要在系统栈和模拟栈中进行切换就可能了,当然这个方法目前还是有缺陷,那就是多线程并发调用它,肯定会有问题.
注:下面均为OD加载后的指令已做过了重定位,基址为0x3B0000
[003B31FC]处为ESP和系统栈的切换临时变量
初始化函数的地址是003B10D8
数据节中模拟栈的地址是003B31F4

1 初始化调用的函数指针设置,
003B3000  00 00 00 00 00 00 00 00 BF B4 D1 A9 C2 DB CC B3  ........看雪论坛
改为
003B3000  D8 10 3B 00 00 00 00 00 BF B4 D1 A9 C2 DB CC B3  ?;.....看雪论坛

2 sub_401062()调用初始化函数, 作用是在分配的堆上构造一个调用栈.
system地址  003B10D8  参数  
在数据节中的内容
003B31F0  00 00 00 00 D8 10 3B 00 60 30 3B 00 F0 31 3B 00  ....?;.`0;.?;.

3 sub_40107C() 分配的空间由 4*0x20 改为 0x7f*0x7f, 指针存放在[3B3048]处
003B107C  /$  6A 20         push    20 ; 修改为 0x7f
003B107E  |.  58            pop     eax
003B107F  |.  6A 04         push    4 ; 修改为 0x7f
003B1081  |.  50            push    eax
003B1082  |.  A3 4C303B00   mov     dword ptr [3B304C], eax
003B1087  |.  E8 24000000   call    003B10B0
003B108C  |.  59            pop     ecx
003B108D  |.  A3 48303B00   mov     dword ptr [3B3048], eax
003B1092  |.  59            pop     ecx
003B1093  \.  C3            retn

4 导出函数的内容如下
003B10D0 >/$  8725 FC313B00 xchg    dword ptr [3B31FC], esp  ;6
003B10D6  \.  C3            retn ;1

5 我将初始化函数放在003B10D8处,初始化函数,附加调用后的恢复功能,代码如下
OpenUrlA:
003B10D0 >/$  8725 FC313B00 xchg    dword ptr [3B31FC], esp ; 交替使用模拟栈和系统分配的栈
003B10D6  \.  C3            retn
003B10D7      90            nop
初始化函数的代码
003B10D8   .  83EC 08       sub     esp, 8 ;若是从system()返回来的则
003B10DB   .  56            push    esi
003B10DC   .  57            push    edi
003B10DD   .  BE F4313B00   mov     esi, 003B31F4 ;模拟栈中返回地址和参数已做过重定位
003B10E2   .  8B3D 48303B00 mov     edi, dword ptr [3B3048] ;堆中分配的空间指针地址
003B10E8   .  6A 7F         push    7F
003B10EA   .  58            pop     eax
003B10EB   .  F7E8          imul    eax
003B10ED   .  8D7C38 EF     lea     edi, dword ptr [eax+edi-11] ; 合适的位置,高地址处双字对齐
003B10F1   .  8BD7          mov     edx, edi
003B10F3   .  A1 14203B00   mov     eax, dword ptr [<&MSVCRT.system>]
003B10F8   .  FC            cld
003B10F9   .  AB            stos    dword ptr es:[edi] ; system入口地址
003B10FA   .  AD            lods    dword ptr [esi] 
003B10FB   .  AB            stos    dword ptr es:[edi] ; 本函数地址
003B10FC   .  AD            lods    dword ptr [esi]
003B10FD   .  AB            stos    dword ptr es:[edi] ; 命令字符串参数
003B10FE   .  8BC6          mov     eax, esi
003B1100   .  5F            pop     edi
003B1101   .  5E            pop     esi
003B1102   .  3BE2          cmp     esp, edx
003B1104   .^ 74 CA         je      short OpenUrlA ;从OpenUrlA来,回OpenUrlA去
003B1106   .  83C4 08       add     esp, 8 ;首次调用
003B1109   .  8910          mov     dword ptr [eax], edx ; 初始化时将模拟栈的地址复制到[3B31FC]
003B110B   .  C3            retn

七 缩小文件尺寸, 节的优化
由于.reloc会被放弃,故将其可以合并到其它的节中,将原先的头尺寸由0x400减少为0x200,同时加上.reloc节的空间,就有1KB,将其合并后最后一节的尾部截去, 就可以得到1.7KB,实际上还有代化的空间.

太晚了,就写到这儿.


PS:麻烦版主在比赛结束后移到『软件调试论坛』

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2
RVA:10D0
OpenUrlA函数大小=13 字节
附件提交次数=1
得分=min[1.0,(13/13)]×100-(1-1)×5=100.0
2008-10-14 20:53
0
游客
登录 | 注册 方可回帖
返回
//