漏洞战争-cve-2012-0774

on under 二进制
4 minute read

0x00 Prepare

1.adobe reader 9.4.0
2.immunity debugger

0x01 分析

打开adobe reader,od附加
f9
adobe reader中打开poc.pdf
    adobe reader崩溃,但是od无法捕获异常,换成immunity debugger可捕获异常位置

重新打开reader,immunity debugger附加
f9
reader打开poc.pdf,异常捕获,中断如下:
    6DD979C9   8D71 04          LEA ESI,DWORD PTR DS:[ECX+4]
    6DD979CC   8B1E             MOV EBX,DWORD PTR DS:[ESI]
    6DD979CE   8919             MOV DWORD PTR DS:[ECX],EBX
    6DD979D0   8BCE             MOV ECX,ESI
    6DD979D2  ^75 F4            JNZ SHORT CoolType.6DD979C8
    6DD979D4   83E8 04          SUB EAX,4
    中断位置为6dd979ce处的MOV DWORD PTR DS:[ECX],EBX,immunity debugger中下面状态栏中显示:access violation when
    wring to 6dfcf000,也即[ecx]所在内存空间不可写,因此导致崩溃,从当前堆栈窗口中找出最上面的return to的地址,右
    键在反汇编窗口跟随,得到当前的6dd979ce处的指令在如下call 调用的函数帧空间中:

    6DD96956   50               PUSH EAX
    6DD96957   FF148D D0BEFA6D  CALL DWORD PTR DS:[ECX*4+6DFABED0]       ; vulfunc
    6DD9695E   59               POP ECX
    将6dd96957处的调用标记为vulfunc,现在要在6dd96957处下断点并查看这个调用过程,但是有aslr机制,重新下断时这里不
    再会是6dd96957,需算出6dd96957与当前dll的偏移再根据偏移在重新运行reader后下断点,alt+e:
    
    Executable modules, item 22
    Base=6DD90000
    Size=0025F000 (2486272.)
    Entry=6DDD866B CoolType.<ModuleEntryPoint>
    Name=CoolType
    File version=5.05.73.1
    Path=C:\Program Files (x86)\Adobe\Reader 9.0\Reader\CoolType.dll
    在alt+e窗口中得到vulfunc在CoolType.dll中,且vulfunc在CoolType.dll中的内存偏移为:6dd96957-6dd90000=6957

重新打开reader并用immu附加,f9,alt+e,发现cooltype.dll的基址不变,仍然是6dd90000,那么前面一步的计算偏移就是多余的
了,看来泉哥在这里的想法不完全正确,这里不用算偏移,应该是操作系统没有为cooltype.dll开aslr.可直接在6dd96957处下断.
后来发现是自己错了,重新运行reader并用immu附加后cooltype.dll的地址会是6dd90000或是69360000,eg.第一次运行reader并
用immu附加后cooltype.dll的基址为6dd90000,关闭reader和immu后,第二次运行reader并用immu附加后cooltype.dll的基址为
69360000,第三次又变回6dd90000,第四次则为69360000,...以此交替.说明cooltype.dll还是开了aslr的.继续用偏移的方法下
断点,重新打开reader,immu附加,第一次cooltype.dll的基址为6dd90000,第二次为69360000,此时在69360000+6957=69366957处
下断

ctrl+g:69366957
f2
    69366955   51               PUSH ECX
    69366956   50               PUSH EAX
    69366957   FF148D D0BE5769  CALL DWORD PTR DS:[ECX*4+6957BED0]
    6936695E   59               POP ECX
    6936695F   59               POP ECX

在69366957处shift+f4下条件记录断点,记录ecx(ecx是虚拟指令索引号),设置为不中断,explanation设成:"index ecx",
expression设成:"ecx"

f9
reader打开poc.pdf
    再次崩溃,由immu捕获崩溃,与上次崩溃信息相同,得到log面板中日志如下:

    ...
    ...
    ...
    ...
    69366957   COND: index ecx = 00000041
    69366957   COND: index ecx = 00000063
    69366957   COND: index ecx = 00000060
    69366957   COND: index ecx = 00000041
    69366957   COND: index ecx = 00000043
    69366957   COND: index ecx = 000000B0
    69366957   COND: index ecx = 00000061
    69366957   COND: index ecx = 00000042
    69366957   COND: index ecx = 00000043
    69366957   COND: index ecx = 00000078
    69366957   COND: index ecx = 00000041
    69366957   COND: index ecx = 00000063
    69366957   COND: index ecx = 00000060
    69366957   COND: index ecx = 00000041
    69366957   COND: index ecx = 00000043
    69366957   COND: index ecx = 000000B0
    69366957   COND: index ecx = 00000061
    69366957   COND: index ecx = 00000042
    69366957   COND: index ecx = 00000043
    69366957   COND: index ecx = 00000078
    69366957   COND: index ecx = 00000041
    69366957   COND: index ecx = 00000060
    69366957   COND: index ecx = 00000060
    69366957   COND: index ecx = 00000026
    693679CE   [18:15:48] Access violation when writing to [6959F000]
    说明是索引号为26的call调用造成了access violation,设置条件断点:当ecx为26时中断

重新打开reader并用immu附加,这次cooltype.dll基址为6dd90000,6dd90000+6957=6dd96957,ctrl+g:6dd96957
    6DD96955   51               PUSH ECX
    6DD96956   50               PUSH EAX
    6DD96957   FF148D D0BEFA6D  CALL DWORD PTR DS:[ECX*4+6DFABED0]       ; vulfunc
    6DD9695E   59               POP ECX
    6DD9695F   59               POP ECX
    6DD96960   3BC6             CMP EAX,ESI

在6dd96957上设置条件断点,shift+f2,设置断点条件为ecx==26
f9
reader打开poc.pdf
    成功中断到6dd96957处,且ecx=26,f7跟进call,汇编指令如下:

    6DD9798B   A1 E023FC6D      MOV EAX,DWORD PTR DS:[6DFC23E0]
    6DD97990   8B0D EC23FC6D    MOV ECX,DWORD PTR DS:[6DFC23EC]
    6DD97996   53               PUSH EBX
    6DD97997   56               PUSH ESI
    6DD97998   8B31             MOV ESI,DWORD PTR DS:[ECX]
    6DD9799A   8D50 FC          LEA EDX,DWORD PTR DS:[EAX-4]
    6DD9799D   3BD6             CMP EDX,ESI
    6DD9799F   57               PUSH EDI
    6DD979A0   72 45            JB SHORT CoolType.6DD979E7
    6DD979A2   8BB9 54010000    MOV EDI,DWORD PTR DS:[ECX+154]
    6DD979A8   3BD7             CMP EDX,EDI
    6DD979AA   73 3B            JNB SHORT CoolType.6DD979E7
    6DD979AC   83C0 FC          ADD EAX,-4
    6DD979AF   8B10             MOV EDX,DWORD PTR DS:[EAX]
    6DD979B1   8BDA             MOV EBX,EDX
    6DD979B3   C1E3 02          SHL EBX,2
    6DD979B6   8BC8             MOV ECX,EAX
    6DD979B8   2BCB             SUB ECX,EBX
    6DD979BA   3BCE             CMP ECX,ESI
    6DD979BC   72 29            JB SHORT CoolType.6DD979E7
    6DD979BE   3BCF             CMP ECX,EDI
    6DD979C0   73 25            JNB SHORT CoolType.6DD979E7
    6DD979C2   85D2             TEST EDX,EDX
    6DD979C4   8B39             MOV EDI,DWORD PTR DS:[ECX]
    6DD979C6   7E 0F            JLE SHORT CoolType.6DD979D7
    6DD979C8   4A               DEC EDX
    6DD979C9   8D71 04          LEA ESI,DWORD PTR DS:[ECX+4]
    6DD979CC   8B1E             MOV EBX,DWORD PTR DS:[ESI]
    6DD979CE   8919             MOV DWORD PTR DS:[ECX],EBX
    6DD979D0   8BCE             MOV ECX,ESI
    6DD979D2  ^75 F4            JNZ SHORT CoolType.6DD979C8
    6DD979D4   83E8 04          SUB EAX,4
    6DD979D7   8938             MOV DWORD PTR DS:[EAX],EDI
    6DD979D9   83C0 04          ADD EAX,4
    6DD979DC   A3 E023FC6D      MOV DWORD PTR DS:[6DFC23E0],EAX
    6DD979E1   8B4424 10        MOV EAX,DWORD PTR SS:[ESP+10]
    6DD979E5   EB 0F            JMP SHORT CoolType.6DD979F6
    6DD979E7   A1 3824FC6D      MOV EAX,DWORD PTR DS:[6DFC2438]
    6DD979EC   C705 3424FC6D 10>MOV DWORD PTR DS:[6DFC2434],1110
    6DD979F6   5F               POP EDI
    6DD979F7   5E               POP ESI
    6DD979F8   5B               POP EBX
    6DD979F9   C3               RETN
    此时eip=6dd9768b,单步跟踪

f8
f8
...
eip=6dd979b3
    此时汇编指令为shl ebx,2,寄存器值如下:

    EAX 6DFC622C CoolType.6DFC622C
    ECX 0577E4E4
    EDX 40000001
    EBX 40000001
    ESP 0014CA20
    EBP 0014CAB4
    ESI 6DFC6220 ASCII "AA"
    EDI 6DFC6344 ASCII "tnfs"
    EIP 6DD979B3 CoolType.6DD979B3
    这里的ebx为0x40000001,shl ebx,2之后得到ebx=0x40000001*4=0x100000004=0x00000004,导致整数溢出,再继续单步跟踪
    到6DD979CE处的MOV DWORD PTR DS:[ECX],EBX应该会出现前面一样的access violation,reader崩溃.

f8
...
eip=6dd979ce
    此时并没有崩溃,因为在6dd979c8到6dd979d2为一个循环,会在这个循环中的某一次中出现access violation使得reader崩
    溃,0x40000001是溢出的关键,它完全是由虚拟指令操作实现的.为了看清0x40000001是怎么出现的,需要知道每个虚拟指令
    索引号对应的call中的汇编指令效果,于是对溢出前的每个虚拟指令索引号对应的CALL DWORD PTR DS:[ECX*4+6DFABED0]
    设置条件记录断点,记录call前与call后虚拟栈顶vm_esp的值及虚拟指令.这里的虚拟栈顶vm_esp并不是指esp中的数据,这
    里的虚拟指令类似于java的虚拟机指令,是"虚拟的",并不是真实栈中的数据,而是对虚拟指令而言的"虚拟栈",如B0 01虚拟
    指令对应将1压栈的动作,这里的压栈是对虚拟指令而言的栈,并不是真实的esp中的栈,要想得到"虚拟栈"中的数据,需要得到
    "虚拟栈"对应的真实内存地址,跟踪B0 01虚拟指令的CALL DWORD PTR DS:[ECX*4+6DFABED0]的处理情况,进行如下操作

重新打开read并用immu附加,这次cooltype.dll的基址为69360000,ctrl+g:69366957,在69366957处下条件断点,设置条件为
ecx=0xB0

f9
reader打开poc.pdf
    成功中断在ecx=b0情况下,对应call的函数帧中指令如下:
            
    69368B05   A1 E0235969      MOV EAX,DWORD PTR DS:[695923E0]
    69368B0A   8B15 EC235969    MOV EDX,DWORD PTR DS:[695923EC]
    69368B10   8D48 04          LEA ECX,DWORD PTR DS:[EAX+4]
    69368B13   3B8A 54010000    CMP ECX,DWORD PTR DS:[EDX+154]
    69368B19   77 18            JA SHORT CoolType.69368B33
    69368B1B   3B0A             CMP ECX,DWORD PTR DS:[EDX]
    69368B1D   76 14            JBE SHORT CoolType.69368B33
    69368B1F   8B4C24 04        MOV ECX,DWORD PTR SS:[ESP+4]
    69368B23   0FB611           MOVZX EDX,BYTE PTR DS:[ECX]
    69368B26   8910             MOV DWORD PTR DS:[EAX],EDX
    69368B28   8305 E0235969 04 ADD DWORD PTR DS:[695923E0],4
    69368B2F   8D41 01          LEA EAX,DWORD PTR DS:[ECX+1]
    69368B32   C3               RETN
    由于B0 01虚拟指令对应的虚拟动作是将1压栈,现在要找到1所在的真实内存位置,f8单步

f8
...
...
f8
eip=69368b26时,edx=1,[eax]=1,对应"虚拟栈顶"vm_esp中的数据
f8
eip=69368b28时,此时已经将1赋值给[eax],此时可以看到[695923e0]=69596240=eax
f8
    eip=69368b2f,此时已经执行完ADD DWORD PTR DS:[695923E0],4,后面再f8再次就执行完call了,执行完call之后要想得到
    "虚拟栈顶"vm_esp中的数据的方法为:查看真实内存中的值[[695923e0]-4],所以要想得到溢出前每个索引对应的call在
    call执行前与call执行后虚拟栈顶的值及虚拟指令,则需要设置条件记录断点,并设置expression为:"[[695923e0]-4]",为
    了观察更多,也记录vm_esp-4中的数据,并在call调用前和调用后分别记录,也即最后这样设置:
    在call的上一句指令处设置条件记录断点,并设置explanation为:"执行前[vm_esp]",设置expression为:"[[695923e0]-4]"
    在call的上一句指令处设置条件记录断点,并设置explanation为:"执行前[vm_esp-4],设置expression为"[[695923e0]-8]"
    在call指令处设置条件记录断点,并设置explanation为:"虚拟指令索引号",设置expression为"ecx"
    在call的下一句指令处设置条件记录断点,并设置explanation为:"执行后[vm_esp]",设置expression为:"[[695923e0]-4]"
    在call的下一句指令处设置条件记录断点,并设置explanation为:"执行后[vm_esp-4],设置expression为"[[695923e0]-8]"
    上面5个设置中都设置不中断且记录expression的值

重新打开read并用immu附加,此时cooltype.dll基址为6dd90000,关键call调用的地址为6dd96957   
ctrl+g:6dd96957,按照上面的5个设置条件记录断点之后便可得到书中对应log记录,再通过分析log得到0x40000001的来源过程.
需注意要在32位系统上调试,如果在64位系统上调试应该设置explanation为vm_esp和vm_esp-8,expression对应为
[[695923e0]-4]和[[695923e0]-0xc].

漏洞分析, 整数溢出
home
github
archive
category