前些天朋友给了一个pdf的poc,让分析一下其漏洞的成因,终于在最近有了头绪,现将分析思路整理归纳一下。
  
        由于以前没有研究过pdf,所以先找到pdf的结构资料及说明文档,大概有所了解后。开始有针对性的对poc进行Fuzzing测试,定位出了文件中0x5455(不同poc可能不一样)开始的一段数据是shellcode。修改代码使之进入死循环。然后打开poc,用softice断下来,程序停在shellcode的入口处。经过几次测试发现,程序不是很稳定的停在一个固定的地址0x3445455,也就是说shellcode不是每次都被加载在相同的位置,但基本上只要不重启系统此地址就不改变。
  所以仍对此处下内存写入断点:
  
  bpm        3445455  w  
  
    断下2次后(次数不固定,跟系统状态有关),跟踪程序运行至0x280b0b
  
  280b0b  ff5530           call  [ebp+30]; [ebp+30h]=[12ceb4+30h]=[12cee4]=12f56c
    
       也就是说此时程序进入堆栈执行,而12f56c的内容是一长串跳转指令,紧接着是一段解码指令,然后跳转至3445455执行此处shellcode。继续往上分析,查看此时堆栈中的返回地址,
  不难得出0x280b0b是在0x7c90e465处子过程中被执行的。
  
    这个溢出中,有一处比较特殊,0x280b0b。起初没有怎么留意,后来在几次尝试后才发现这个地址是固定的,即每次都要通过此处来跳转到堆栈中去执行。而且此处就在unicode.nls的空间内,而unicode.nls在系统中的位置基本都是固定不变的。分析0x280b0b处的作用,与一般的溢出流程作比较,0x280b0b就是一个跳板,将程序流程指向到堆栈中去执行,相当于广义上的jmp esp/ebx之类的作用。所以在程序空间肯定能找到字节 0b 0b 28 00,并且这个字符是作为一个地址存放在这个空间的某个地址addr1,addr1有可能是存放函数返回地址,也有可能是  存放着函数的指针,经跟踪发现addr1存放的是异常处理函数的地址,在后续利用中会用到。
    在程序的执行过程中addr1被字节0b 0b 28 00 覆盖。
  
    故,  bpx  7c90e465
  
                s      0000   L   ffffffff   0b 0b 28 00
  
          found   12d280
  
      12d280  0b 0b 28 00 eb 06 eb 06-0b 0b 28 00 eb 06 eb 06  
  
    发现,程序对12d280后的连续区域写入0b 0b 28 00 eb 06 eb 06,而addr1也应该在此区域里,所以,对12d280下内存写入断点    
    
    重新打开poc,当向12d280写入字节0b 0b 28 00时,程序停在AcroRd32.dll(漏洞就存在于这个文件中)空间里。
  
    c1070b  6689447590  mov  [esi*2+ebp-70],ax ;(没有进行严格长度检测,                 导致写入地址违规)
    c10710            inc     esi
    c10711           cmp   esi,2000 ;(没有进行严格长度检测)
    c10717           jnz    c1073f  
    ......
    c1073f      inc    ebx  
    c10740     inc   ebx
    c10741    dec  dword ptr [ebp-74]
    c10744    cmp    dword ptr [ebp-71],00
    c10748    jnz   c10651
    ......
    c10651    movzx  eax, word ptr [ebx]
    c10654    cmp  ax,25
    c10658    jnz  c1070b
  
    跟踪调试,当esi = 16c0时(esi < 2000h)
  c1070b  mov  [esi*2+ebp-70],ax ; [esi*2+ebp-70] = [130000]
  ......
    写入地址访问异常,调用异常处理结构处理,此时程序跳至7c90e45c,而内存地址7c90e45c对应ntdll.dll的KiUserExceptionDispatcher导出函数。
  
 漏洞成因:没有进行严格长度检测(esi < 2000h),导致写入地址违规(0x130000),触发异常,而在本利用中,覆盖了异常处理函数的地址,使之经过跳板指向自己布置的shellcode,从而成功利用。
  
        主要是和大家交流一下分析思路,出于安全考虑,poc就不给出来了。