首页
社区
课程
招聘
[原创]CVE-2011-0104 Excel TOOLBARDEF Record栈溢出漏洞分析与利用
发表于: 2021-9-2 16:22 17400

[原创]CVE-2011-0104 Excel TOOLBARDEF Record栈溢出漏洞分析与利用

2021-9-2 16:22
17400

这篇文章重新回到栈溢出漏洞的分析,CVE-2011-0104是Excel在解析XLB文件中的TOOLBARDEF记录时,未正确进行数据验证导致的栈溢出漏洞。在进行这个漏洞分析时,我并没有完全遵循《漏洞战争》中的分析流程,准确的说,我做了一些扩展,参考Abysssec的分析文章,从漏洞利用的角度进一步分析了触发漏洞的文件格式,并对其进行修改,最后成功在我自己的环境下实现了漏洞利用。

操作系统:WinXP Pro SP3

Office: 2003 SP3

测试文件:书中使用的是由src.xlb构造而成的exploit.xlb文件,但是我在实验过程中,发现src.xlb文件一开始触发的异常和书中更相似,可能是环境不同的缘故。由于引入了shellcode代码后,栈中的数据会更加复杂,不利于分析。而src.xlb文件本身能够触发异常,已经足够进行漏洞分析了,所以我选择从这个文件开始进行漏洞分析。

打开excel,使用windbg附加,然后打开src.xlb文件,程序中断:

此时的栈中情况:

可以看到大量的0x90字节,已知这是一个栈溢出漏洞,所以大致可以猜出此时用于溢出栈的数据已经复制到了栈中,但是可能由于环境的问题,相关数据的偏移是错误的,所以才产生了异常。

由于缺少symbol,很多信息都无法查看,直接在IDA打开EXCEL.EXE文件,定位到地址300ce361,可以找到这个地址所在的函数地址为sub_300CE252,直接按照书中的说法,定义该函数为crashFun

确定了异常函数的地址,这次重新调试,并在crashFun处设置断点,到达后注意添加快照。根据之前的猜测,栈溢出就应该发生在这个函数调用之后,如果栈溢出的数据设置正常,应该会把这个函数的返回地址覆盖掉,只是这里由于环境的问题,数据偏移是错误的,但是该覆盖掉的数据应该还是会覆盖掉,所以直接在crashFunc的入口处设置一个栈顶元素的访问断点(栈顶元素保存的就是返回地址),然后继续执行。

所以应该就是这里的rep指令在进行数据复制的时候,导致了栈溢出。rep指令的地址是300ce3c8,在IDA中找到这个地址,确定其所在的函数为sub_300CE380,沿用书中的说法,将其定义为vulFun

注意一下在vulFun中,qmemcpy函数在数据复制时发生栈溢出,而其中的length参数有两个来源:

v6v5是两个内存中的值,v4来源于栈中的第二个参数a3length就取两者中的偏小值。不过从qmemcpy后面的代码来看,整个数据复制的循环更像是由v4在控制,后续调试看看。

在这里设置一个快照,然后回退到crashFun入口点的时候,注意crashFun对栈空间的分配:

vulFun设置一个断点,继续执行:

此时栈中的第二个参数是4,第一个参数是001379fc,这是数据复制的目的地址,看来这次应该不是导致栈溢出的那次函数调用,但还是继续跟一下,确定v6v5是两个值多大。

这两个值相差还是蛮大了,虽然会被修改,但是相差的量级变化不大,所以length主要还是由栈中的第二个参数控制。

由于此次调用并不是导致数据溢出的那次调用,我们继续执行,还是到达vulFun的起始位置

根据栈中保存的数据,此次数据复制的目的地址是0013aa3b,长度为0x300。还记得我们刚到达crashFun时记录的栈顶和栈基址吗?栈顶是13aa30,栈基址是13aa8c,所以这次数据复制的长度远超过函数栈帧覆盖的范围,导致了溢出的发生。

接下来就是所谓的污点追踪,查看导致溢出的数据长度0x300的来源。

栈中的第一个元素306df0e1vulFunc的返回地址,从IDA中查找,得到306df0e1所在的函数为sub_306DEEFE,也就是这个函数调用了vulFunc

在IDA中查看该函数,F5查看伪代码有500+行,全都分析过来肯定不现实。大致浏览一下整个函数,关注以下几句代码(如果自己分析还是要去IDA里面看,但看下面几句肯定看不明白):

有一个很重要的函数readData,位于0x300CE402。名字是我自己起的,从它的代码来看,很明显是在一个src处读取数据。

我猜测这个函数就是在读取xlb文件内容。这里注意一下,程序使用一个保存在内存中的数值作为src数组的索引值,这里命名为了src_idx,每次readData读取两个字节,这个值也会增加2,之后还会遇到这个值。

接下来在函数sub_306DEEFE下断点(就是这个函数调用了vulFun,我们把这个函数叫做call_vulFun),调试跟踪一下。

重新返回crashFun函数入口点的快照,设置断点,继续执行。

在进一步单步调试之前,我们先看一下用来测试的xlb文件src.xlb的格式,使用py-office-tools对该文件进行分析:

得到结果很长,这里没办法都贴出来,但是里面有一些数据有助于我们在调试的时候进行定位:

接下来开始调试,首先进入readData()函数

注意到这里的3f7a,就是结果中的[*]Dumping Workbook stream 0x3f7a (16250) bytes...,这一数值在之前确定v5v6的时候也遇到过。

接下来执行的代码:

一开始肯定是没有超过的,所以并没有跳转:

注意这里就从偏移0x14的位置读取了一个数值0xa7,也就是说此时src_idx的值为0x14,首先注意它是从哪里读取的——3085d400,看一下这里的数据:

如果在010editor中打开src.xlb文件,可以找到这部分数据位于偏移0x600处。如果和pyOffice的输出结果做对比,可以发现这部分数据就是Record BOF [0x809 (2057)],紧跟其后的就是Record TOOLBARDEF [0xa7 (167)]

根据参考资料3中对xls文件格式的理解,在调用call_vulFun这个函数之前,程序应该是先提取出来了一个长度为0x3f7a的Workbook stream,然后由call_vulFun函数进行处理,BOF记录标志着一个substream的起始位置,call_vulFun略过BOF记录,读入下一个记录的标志(0xa7),根据这个标志的不同取值进行不同的处理。

接下来继续往下调试,会发现程序读取了TOOLBARDEF记录的长度0x4,此时src_idx的值为0x16,读取完之后的值应该是0x18

之后程序通过vulFunc将这四个字节复制到了栈中,注意在vulFunc中,虽然没有通过readData读取数据,但是因为已知了记录长度为4,所以直接将src中后续的四个字节读取到了栈中,并为src_idx增加了四个字节,也就是说,此时src_idx的值为0x1c

然后有一系列的if语句,但是判断都没有通过,最终到达了判断tag是否为0xa7的语句,判断通过。

接下来有一系列的计算很有意思:

注意这里最后获得的esi寄存器中的值,就是在2.4小节之前获得的发生溢出时数据复制的目的地址。

也就是说,程序在复制完TOOLBARDEF记录中的四个字节数据之后,根据它的cbtn字段,将接下来的数据复制目的地址增加了一大段。这里我的理解是,TOOLBARDEF记录中的len字段应该和cbtn字段是有关系的,可是这里的数据是自己构造的,len表示长度只有4字节,所以复制数据的时候只复制了4字节,但是根据cbtn字段计算的空间规模却很大,导致程序把栈中一大块未定义的空间当作了正常的数据。

到目前为止程序执行的代码如下:

接下来程序在循环处理这部分未定义的数据:

注意这里eax寄存器中的值为00137a03,本来TOOLBARDEF记录中的四字节数据是复制到了001379fc之后的四个字节,此时eax已经指向了之后未定义的那部分栈中数据,得到了90909090。这个数据应该是之前有栈帧占用这部分空间,残留的数据内容。

在循环处理数据的过程中,每读取一次数据之后,程序会做一系列的判断和处理,最终发生栈溢出的数据复制操作就发生在这期间:

如果在306df06c这里设置一个断点,然后执行,可以看到程序会多次断在这里,eax的值不断递增:

一开始读取到的都是0x90909090,这个取值在进行v77 & 0x12F0000操作的时候,结果是0,因此不会执行到vulFun的位置。

同时在vulFun的位置设置一个断点,然后继续执行,

当程序读取到00137b67的位置时,获得数值2cd5e9752cd5e975 & 0x12F0000= 0x50000,可以通过判断条件。

按照之前的推断,在执行vulFun之前,调用readData读取到的内容应该是src中偏移src_idx,即偏移0x1c处的数据。为了确认这一点,回退一下快照,这次不要在vulFun的位置设置断点,只在306df06c设置一个条件断点,然后继续执行:

之后开始单步,进入到readData中之后,发现读取的确实是偏移0x1c处的数据:

和pyOffice工具得到的输出相对比,就是位于TOOLBARDEF记录之后的CONTINUE记录,用0x3c标签表示。也正是0x3c这个数值,让程序继续执行到了后面的vulFun函数。

继续向下单步,接下来程序仍旧调用readData,读取了CONTINUE记录的长度为0x300,这个数值也会传递到vulFun中,作为数据复制的长度。注意到此时,由于读取了两次数据,src_idx的值应该是0x20

上面是IDA中获得的伪代码,可以看出在调用vulFun之前的基本流程,最后调用vulFun的时候,查看栈中数据:

可以看到复制的目的地址和长度。也就是说,程序会把src偏移0x20开始的0x300个字节的数据复制到0013aa3b的位置。

所以现在可以确定数据复制长度0x300来自TOOLBARDEF记录后面的CONTINUE记录的长度。

现在已经确定了0x300的来源,但是我还想要弄清楚后面异常发生的原因,怎样构造exploit文件实现漏洞利用。

到目前为止call_vulFun这个函数差不多看完了,因为异常发生在调用call_vulFuncrashFun函数中,所以我们可以直接跳过这个函数,回到crashFun中。直接在IDA中定位到返回地址的位置,下断点:

注意这里我是在返回地址的前几个指令下的断点,因为在参考资料2中:

Stack overflows are not hard to exploit at all ! but as we have both /GS , SAFESEH here. because given that we are destined to memcpy we can change it so that it begins to overwrite the stack after GS.

所以我检查了一下retn之前的几句指令,发现它确实在做一个检查:

注意这里,程序从0013aa04中取出了一个数值bcdcb8c1,进行了检查:

如果检查不通过程序就退出了。

所以栈中位置0013aa04的数值不能被修改。

这下可以回到crashFun函数了。结束了call_vulFun函数的调用,程序流程很快就跳转了发生异常的位置:

注意到,程序从0013aab8的位置读取了四个字节的数据,并与0进行比较,如果比较成功,程序会进行一些数据的更新,并成功执行到retn语句。但是这里比较失败了,所以最终触发了异常。

我在调试的时候,手工把eax的值修改成了0,让跳转发生,并最终单步到达retn语句:

注意此时esp寄存器的值为0013aa90,如果进行漏洞利用,我们希望这里保存的就是跳转地址了,比如jmp esp指令。

所以现在有两个特殊位置的数据需要注意:

在第2节的最后,我们已经确定,程序会把src偏移0x20开始的0x300个字节的数据复制到0013aa3b的位置。经过计算:

根据上面得到的两个特殊位置,我尝试对src.xlb中这两个位置的数据进行修改。

首先确定jmp esp指令地址:

之前在看Exploit编写系列教程的时候,里面提到了一个工具findjmp.exe:

src.xlb文件中,对应于我们之前在IDA中的src的位置,是在偏移0x600的位置,也就是BOF记录起始的位置。

从这里开始找到偏移0x9D的位置,修改四个字节为00 00 00 00;找到偏移0x75的位置,修改四个字节为67 86 86 7c

由于程序最后执行的返回指令是retn 2Ch,所以在返回地址的后面要预留0x2C字节,再写入真正的shellcode,我没有仔细计算长度,只是预留了足够的位置,写入了0xCC,这里只做测试,所以先不放入真正的shellcode。

修改好对应位置之后,重新打开excel,使用windbg附加,并在异常发生前的位置0x300ce354处设置断点,打开测试文件:

可以看到程序中断的位置,在0013aab8读取数值为0,数据修改成功,单步继续执行,到达retn语句:

注意到此时栈顶的数据是7c868667,正是我们之前搜索到的call esp指令所在的位置,数据修改成功,继续单步执行,到达call esp

步入之后,到达了nop指令的位置,继续向前单步,到达了我们设置的int 3指令:

测试成功,现在可以替换成真正的shellcode了!

因为直接修改太麻烦了,所以这里使用脚本生成exploit文件,可以参考书中提供的exploit.py脚本:

使用上述脚本生成的exploit.xlb,打开后可以成功弹出计算器。

图片描述

从上面的脚本中可以看出需要修改的数据并不多,这时由于src.xlb中本身已经包含了一些特殊数据,这部分内容不需要再做修改,所以我并没有写相关代码。

但是在书中原本提供的python脚本中,也提供了这一部分数据,可以在这里看一下:

可以看到,这个脚本在偏移0x614之后就开始对src.xlb文件内容进行替换了,但是实际上前半部分替换的内容和src.xlb中原本的内容是一样的,不过这样显然更清晰,因为这些内容也和漏洞利用相关。

除此之外,脚本中返回地址放置的位置更加靠前,与我的测试环境不符,也正是由于这个原因,我在使用书中自带的exploit.xlb时,没能弹出计算器。

在前面的几周中,我根据漏洞原理的不同分析了几种不同的漏洞,也遇到了IE漏洞这个难啃的骨头,再回过头来看栈溢出漏洞,能明显感觉到分析的过程轻松了很多。

漏洞的前半部分分析根据书中所说的“污点追踪”的方法,确定了要找到0x300的数据来源,但是之后确定call_vulFunvalFun的调用关系,src.xlb文件中数据对于程序执行流程的影响,都需要一步步的在调试器中跟踪,并分析IDA中的代码,能够分析下来,一定要感谢之前调试IE漏洞的经历。

之前开始学习的Exploit编写系列教程,对于此次漏洞分析也很有帮助,可以感到对整个漏洞利用的流程掌握更加清晰,而且在调试过程中,会很快想到应该在哪个位置下断点。

关于漏洞利用方法,还有一点技巧是在看Abysssec的文章时注意到的,因为这个漏洞可以根据cbtn字段设置数据复制的目标地址,所以可以利用这个方法绕过程序中本身存在的/GS , SAFESEH保护手段。这也是漏洞利用文件中,cbtn要设置那么大的值的原因。

 
 
(8e4.e2c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=90909090 ebx=00000002 ecx=00000006 edx=3160ff00 esi=00000000 edi=00000400
eip=300ce361 esp=0013aa24 ebp=0013aa8c iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010286
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE -
EXCEL!Ordinal41+0xce361:
300ce361 8908            mov     dword ptr [eax],ecx  ds:0023:90909090=????????
(8e4.e2c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=90909090 ebx=00000002 ecx=00000006 edx=3160ff00 esi=00000000 edi=00000400
eip=300ce361 esp=0013aa24 ebp=0013aa8c iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010286
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE -
EXCEL!Ordinal41+0xce361:
300ce361 8908            mov     dword ptr [eax],ecx  ds:0023:90909090=????????
0:000> dd esp
0013aa24  0013c854 00000000 00000002 bcdcb8c1
0013aa34  0013aa8c 40000002 3bd5d6df 3bd5d6df
0013aa44  00000000 00000000 90909090 90909090
0013aa54  90909090 90909090 90909090 90909090
0013aa64  90909090 90909090 90909090 90909090
0013aa74  90909090 90909090 90909090 90909090
0013aa84  90909090 00000000 90909090 90909090
0013aa94  90909090 90909090 90909090 90909090
0:000> dd esp
0013aa24  0013c854 00000000 00000002 bcdcb8c1
0013aa34  0013aa8c 40000002 3bd5d6df 3bd5d6df
0013aa44  00000000 00000000 90909090 90909090
0013aa54  90909090 90909090 90909090 90909090
0013aa64  90909090 90909090 90909090 90909090
0013aa74  90909090 90909090 90909090 90909090
0013aa84  90909090 00000000 90909090 90909090
0013aa94  90909090 90909090 90909090 90909090
 
0:000> ba r4 esp
0:000> g
Breakpoint 1 hit
eax=00000300 ebx=00000300 ecx=000000a8 edx=00000300 esi=3085d480 edi=0013aa9b
eip=300ce3c8 esp=001379dc ebp=0013aa3b iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
EXCEL!Ordinal41+0xce3c8:
300ce3c8 f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:0013aa9b=13c85400 ds:0023:3085d480=90909090
0:000> bl
0:000> ba r4 esp
0:000> g
Breakpoint 1 hit
eax=00000300 ebx=00000300 ecx=000000a8 edx=00000300 esi=3085d480 edi=0013aa9b
eip=300ce3c8 esp=001379dc ebp=0013aa3b iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
EXCEL!Ordinal41+0xce3c8:
300ce3c8 f3a5            rep movs dword ptr es:[edi],dword ptr [esi] es:0023:0013aa9b=13c85400 ds:0023:3085d480=90909090
0:000> bl
char *__userpurge vulFun@<eax>(char *dst@<ebp>, char *a2, unsigned int a3, unsigned int a4)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
 
  v4 = a3;
  if ( !a3 )
    return 0;
  if ( a3 > a4 )
  {
    sub_300BF683(dword_3085C4B4, 6);
    goto LABEL_15;
  }
  v5 = dword_30861408;
  v6 = dword_3085D3F8;
  dst = a2;
  do
  {
    if ( v5 >= v6 )
    {
      v9 = v4;
      if ( v4 > 0x4000 )
LABEL_15:
        v9 = 0x4000;
      sub_300F975F(v9);
      v5 = dword_30861408;
      v6 = dword_3085D3F8;
    }
    length = v6 - v5;
    if ( v4 < length )
      length = v4;
    qmemcpy(dst, (char *)dword_3085D400 + v5, length);// 这里发生栈溢出
    v4 -= length;
    v5 = length + dword_30861408;
    dst += length;
    dword_30861408 += length;
    if ( !v4 )
      break;
    v6 = dword_3085D3F8;
  }
  while ( dword_3085D3F8 == 0x4000 );
  return (char *)(dst - a2);
}
char *__userpurge vulFun@<eax>(char *dst@<ebp>, char *a2, unsigned int a3, unsigned int a4)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
 
  v4 = a3;
  if ( !a3 )
    return 0;
  if ( a3 > a4 )
  {
    sub_300BF683(dword_3085C4B4, 6);
    goto LABEL_15;
  }
  v5 = dword_30861408;
  v6 = dword_3085D3F8;
  dst = a2;
  do
  {
    if ( v5 >= v6 )
    {
      v9 = v4;
      if ( v4 > 0x4000 )
LABEL_15:
        v9 = 0x4000;
      sub_300F975F(v9);
      v5 = dword_30861408;
      v6 = dword_3085D3F8;
    }
    length = v6 - v5;
    if ( v4 < length )
      length = v4;
    qmemcpy(dst, (char *)dword_3085D400 + v5, length);// 这里发生栈溢出
    v4 -= length;
    v5 = length + dword_30861408;
    dst += length;
    dword_30861408 += length;
    if ( !v4 )
      break;
    v6 = dword_3085D3F8;
  }
  while ( dword_3085D3F8 == 0x4000 );
  return (char *)(dst - a2);
}
length = v6 - v5;
if ( v4 < length )
  length = v4;
length = v6 - v5;
if ( v4 < length )
  length = v4;
 
300ce252 55              push    ebp
300ce253 8bec            mov     ebp,esp   // ebp <- esp = 13aa8c
300ce255 83ec5c          sub     esp,5Ch   // esp = 13aa30
300ce252 55              push    ebp
300ce253 8bec            mov     ebp,esp   // ebp <- esp = 13aa8c
300ce255 83ec5c          sub     esp,5Ch   // esp = 13aa30
0:000> bp 300CE380
0:000> g
Breakpoint 1 hit
eax=306def87 ebx=00002020 ecx=00000018 edx=00003f79 esi=00000004 edi=001379fc
eip=300ce380 esp=001379ec ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce380:
300ce380 53              push    ebx
0:000> dd esp l3
001379ec  306defad 001379fc 00000004
0:000> bp 300CE380
0:000> g
Breakpoint 1 hit
eax=306def87 ebx=00002020 ecx=00000018 edx=00003f79 esi=00000004 edi=001379fc
eip=300ce380 esp=001379ec ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce380:
300ce380 53              push    ebx
0:000> dd esp l3
001379ec  306defad 001379fc 00000004
0:000> p
eax=306def87 ebx=00000004 ecx=00000018 edx=00003f79 esi=00000004 edi=001379fc
eip=300ce397 esp=001379e8 ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce397:
300ce397 8b1508148630    mov     edx,dword ptr [EXCEL!DllGetLCID+0x10bda (30861408)] ds:0023:30861408=00000018
0:000> p
eax=306def87 ebx=00000004 ecx=00000018 edx=00000018 esi=00000004 edi=001379fc
eip=300ce39d esp=001379e8 ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce39d:
300ce39d a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)] ds:0023:3085d3f8=00003f7a
0:000> p
eax=306def87 ebx=00000004 ecx=00000018 edx=00003f79 esi=00000004 edi=001379fc
eip=300ce397 esp=001379e8 ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce397:
300ce397 8b1508148630    mov     edx,dword ptr [EXCEL!DllGetLCID+0x10bda (30861408)] ds:0023:30861408=00000018
0:000> p
eax=306def87 ebx=00000004 ecx=00000018 edx=00000018 esi=00000004 edi=001379fc
eip=300ce39d esp=001379e8 ebp=00139ad8 iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
EXCEL!Ordinal41+0xce39d:
300ce39d a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)] ds:0023:3085d3f8=00003f7a
 
0:000> g
Breakpoint 1 hit
eax=ffffefe1 ebx=000000ff ecx=ffffcfc1 edx=00003f79 esi=0013aa3b edi=0000303c
eip=300ce380 esp=001379ec ebp=00139ad8 iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
EXCEL!Ordinal41+0xce380:
300ce380 53              push    ebx
0:000> dd esp l3
001379ec  306df0e1 0013aa3b 00000300
0:000> g
Breakpoint 1 hit
eax=ffffefe1 ebx=000000ff ecx=ffffcfc1 edx=00003f79 esi=0013aa3b edi=0000303c
eip=300ce380 esp=001379ec ebp=00139ad8 iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
EXCEL!Ordinal41+0xce380:
300ce380 53              push    ebx
0:000> dd esp l3
001379ec  306df0e1 0013aa3b 00000300
 
 
v71 = readData();
...
else if ( v71 == 0xA7 )
{
    v13 = readData();
    ...
    v73 = v13;
    ...
    vulFun((char *)&v50, (char *)v9, v73, -3 - v14 + v15);
...
v71 = readData();
...
else if ( v71 == 0xA7 )
{
    v13 = readData();
    ...
    v73 = v13;
    ...
    vulFun((char *)&v50, (char *)v9, v73, -3 - v14 + v15);
...
int readData()
{
  v0 = stream_length;
  v1 = src_idx;
  if ( src_idx >= (stream_length - 1) ) {
    ...
  }
  else {
    result = *&src[src_idx];
    src_idx += 2;
  }
  return result;
}
int readData()
{
  v0 = stream_length;
  v1 = src_idx;
  if ( src_idx >= (stream_length - 1) ) {
    ...
  }
  else {
    result = *&src[src_idx];
    src_idx += 2;
  }
  return result;
}
 
 
pyOffice.py -f src.xlb > src.txt
pyOffice.py -f src.xlb > src.txt
[*]Opening file ..\src.xlb
[*]Listing streams/storages:
 
Warning: OLE type 0x8 not in types
 
[**]Detected Excel file ..\src.xlb
********************************************************************************
[*]Dumping Workbook stream 0x3f7a (16250) bytes...
 
[ii]BOF record: current count 1
[0]Record BOF [0x809 (2057)] offset 0x0 (0), len 0x10 (16) (Beginning of File)
        WORD vers = 0x600 (1536)
        WORD dt = 0x400 (1024)
        WORD rupBuild = 0x1faa (8106)
        WORD rupYear = 0x7cd (1997)
        DWORD bfh = 0x500c9 (327881)
        DWORD sfo = 0x406 (1030)
[1]Record TOOLBARDEF [0xa7 (167)] offset 0x14 (20), len 0x4 (4) (Toolbar Definition:)
        BYTE fUnnamed = 0xb0 (176)
        WORD cbtn = 0xc0f (3087)
        Field 'rgbbtndef' is variable length, dumping rest of record:
            0000000000   00                                                 .
[2]Record CONTINUE [0x3c (60)] offset 0x1c (28), len 0x300 (768) (Continues Long Records)
        Field 'data' is variable length, dumping rest of record:
            0000000000   40 DF D6 D5 3B DF D6 D5 3B 00 00 00 00 00 00 00    @...;...;.......
            0000000010   00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
            0000000020   90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
            0000000030   90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
......
[*]Opening file ..\src.xlb
[*]Listing streams/storages:
 
Warning: OLE type 0x8 not in types
 
[**]Detected Excel file ..\src.xlb
********************************************************************************
[*]Dumping Workbook stream 0x3f7a (16250) bytes...
 
[ii]BOF record: current count 1
[0]Record BOF [0x809 (2057)] offset 0x0 (0), len 0x10 (16) (Beginning of File)
        WORD vers = 0x600 (1536)
        WORD dt = 0x400 (1024)
        WORD rupBuild = 0x1faa (8106)
        WORD rupYear = 0x7cd (1997)
        DWORD bfh = 0x500c9 (327881)
        DWORD sfo = 0x406 (1030)
[1]Record TOOLBARDEF [0xa7 (167)] offset 0x14 (20), len 0x4 (4) (Toolbar Definition:)
        BYTE fUnnamed = 0xb0 (176)
        WORD cbtn = 0xc0f (3087)
        Field 'rgbbtndef' is variable length, dumping rest of record:
            0000000000   00                                                 .
[2]Record CONTINUE [0x3c (60)] offset 0x1c (28), len 0x300 (768) (Continues Long Records)
        Field 'data' is variable length, dumping rest of record:
            0000000000   40 DF D6 D5 3B DF D6 D5 3B 00 00 00 00 00 00 00    @...;...;.......
            0000000010   00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
            0000000020   90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
            0000000030   90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90    ................
......
0:000> t
eax=00000000 ebx=00000002 ecx=00000000 edx=00139a28 esi=00000000 edi=00000000
eip=300ce402 esp=00139a18 ebp=00139ad8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
EXCEL!Ordinal41+0xce402:
300ce402 a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)] ds:0023:3085d3f8=00003f7a
0:000> t
eax=00000000 ebx=00000002 ecx=00000000 edx=00139a28 esi=00000000 edi=00000000
eip=300ce402 esp=00139a18 ebp=00139ad8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
EXCEL!Ordinal41+0xce402:
300ce402 a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)] ds:0023:3085d3f8=00003f7a
 
300ce402 a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)]    // 3f7a
300ce407 8b0d08148630    mov     ecx,dword ptr [EXCEL!DllGetLCID+0x10bda (30861408)]   // 这里保存的是索引值
300ce40d 8d50ff          lea     edx,[eax-1]
300ce410 3bca            cmp     ecx,edx              // 检查索引值是不是超过了stream的范围
300ce412 0f8d20690200    jge     EXCEL!Ordinal41+0xf4d38 (300f4d38)
300ce402 a1f8d38530      mov     eax,dword ptr [EXCEL!DllGetLCID+0xcbca (3085d3f8)]    // 3f7a
300ce407 8b0d08148630    mov     ecx,dword ptr [EXCEL!DllGetLCID+0x10bda (30861408)]   // 这里保存的是索引值
300ce40d 8d50ff          lea     edx,[eax-1]
300ce410 3bca            cmp     ecx,edx              // 检查索引值是不是超过了stream的范围
300ce412 0f8d20690200    jge     EXCEL!Ordinal41+0xf4d38 (300f4d38)
0:000> p
eax=00003f7a ebx=00000002 ecx=00000014 edx=00003f79 esi=00000000 edi=00000000
eip=300ce418 esp=00139a18 ebp=00139ad8 iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000293
EXCEL!Ordinal41+0xce418:
300ce418 0fb78100d48530  movzx   eax,word ptr EXCEL!DllGetLCID+0xcbd2 (3085d400)[ecx] ds:0023:3085d414=00a7
0:000> p
eax=00003f7a ebx=00000002 ecx=00000014 edx=00003f79 esi=00000000 edi=00000000
eip=300ce418 esp=00139a18 ebp=00139ad8 iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000293
EXCEL!Ordinal41+0xce418:
300ce418 0fb78100d48530  movzx   eax,word ptr EXCEL!DllGetLCID+0xcbd2 (3085d400)[ecx] ds:0023:3085d414=00a7
0:000> db 3085d400
3085d400  09 08 10 00 00 06 00 04-aa 1f cd 07 c9 00 05 00  ................
3085d410  06 04 00 00 a7 00 04 00-b0 0f 0c 00 3c 00 00 03  ............<...
3085d420  40 df d6 d5 3b df d6 d5-3b 00 00 00 00 00 00 00  @...;...;.......
3085d430  00 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d440  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d450  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d460  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d470  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0:000> db 3085d400
3085d400  09 08 10 00 00 06 00 04-aa 1f cd 07 c9 00 05 00  ................
3085d410  06 04 00 00 a7 00 04 00-b0 0f 0c 00 3c 00 00 03  ............<...
3085d420  40 df d6 d5 3b df d6 d5-3b 00 00 00 00 00 00 00  @...;...;.......
3085d430  00 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d440  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d450  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d460  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
3085d470  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
 
 
 
...
qmemcpy(dst, src + v5, length);            
v4 -= length;
v5 = length + src_idx;
dst += length;
src_idx += length;
...
...
qmemcpy(dst, src + v5, length);            
v4 -= length;
v5 = length + src_idx;
dst += length;
src_idx += length;
...
 
306df004 833da01c863005  cmp     dword ptr [EXCEL!DllGetLCID+0x11472 (30861ca0)],5        // 这里保存的值没弄清楚是什么,但是这里保存的是6
306df00b 8d0437          lea     eax,[edi+esi]                // esi=00000004 edi=001379fc -> eax=00137a00  edi保存的是之前复制4个字节时栈的起始地址
306df00e 0f9dc2          setge   dl                           // 根据比较结果,dl设置成1
306df011 894574          mov     dword ptr [ebp+74h],eax     
306df014 668b4701        mov     ax,word ptr [edi+1]          // 读取TOOLBARDEF中的cbtn字段:0xc0f
306df018 0fbff0          movsx   esi,ax                       // esi = 0xc0f
306df01b 897538          mov     dword ptr [ebp+38h],esi
306df01e 8d541202        lea     edx,[edx+edx+2]              // edx = 4
306df022 0faff2          imul    esi,edx                      // esi = 0xc0f*4 = 0x303c
306df025 8d4f03          lea     ecx,[edi+3]                  // ecx = 1379ff
306df028 03f1            add     esi,ecx                      // esi = 13aa3b
306df004 833da01c863005  cmp     dword ptr [EXCEL!DllGetLCID+0x11472 (30861ca0)],5        // 这里保存的值没弄清楚是什么,但是这里保存的是6
306df00b 8d0437          lea     eax,[edi+esi]                // esi=00000004 edi=001379fc -> eax=00137a00  edi保存的是之前复制4个字节时栈的起始地址
306df00e 0f9dc2          setge   dl                           // 根据比较结果,dl设置成1
306df011 894574          mov     dword ptr [ebp+74h],eax     
306df014 668b4701        mov     ax,word ptr [edi+1]          // 读取TOOLBARDEF中的cbtn字段:0xc0f
306df018 0fbff0          movsx   esi,ax                       // esi = 0xc0f
306df01b 897538          mov     dword ptr [ebp+38h],esi
306df01e 8d541202        lea     edx,[edx+edx+2]              // edx = 4
306df022 0faff2          imul    esi,edx                      // esi = 0xc0f*4 = 0x303c
306df025 8d4f03          lea     ecx,[edi+3]                  // ecx = 1379ff
306df028 03f1            add     esi,ecx                      // esi = 13aa3b
 
 
...
  v70 = 0;
  tag = readData();                             // 读取数据 得到0xa7
  length = readData();                          // 读取TOOLBARDEF记录的长度,得到0x4
  v76 = length;
  v72 = 0;
  v67 = 0;
  if ( dword_30861C10 ) {
    ...
  }
  else
  {
    (sub_30007AD0)(v47[0]);                     // 这里根据调试应该是在分配足够的栈空间
                                                // 直接将esp减少了0x2020
    stack_start = v47;
    v73 = v47;
    v58 = 0x2020;
  }
  while ( tag != 0xA && tag != 0xC0 )
  {
    vulFun(&v53, stack_start, length, 0x2020u); // 读入TOOLBARDEF的四个字节,放入栈中
                                                // 接下来的几个判断都没有通过
    ...
      else if ( tag == 0xA7 )                   // 直到这里,判断通过
      {
        cntn = &stack_start[length];
        v76 = &stack_start[length];
        LOWORD(cntn) = *(stack_start + 1);      // 读取TOOLBARDEF中的cntn字段:0xc0f
        v61 = cntn;
        new_dst_addr = &stack_start[(2 * (dword_30861CA0 >= 5) + 2) * cntn + 3];// 这里根据cntn得到了一个很大的偏移量
        v71 = cntn;
        four_bytes_end = (stack_start + 3);     // 指向的是复制的四个字节的结束位置
        v75 = 2 * (dword_30861CA0 >= 5) + 2;
...
  v70 = 0;
  tag = readData();                             // 读取数据 得到0xa7
  length = readData();                          // 读取TOOLBARDEF记录的长度,得到0x4
  v76 = length;
  v72 = 0;
  v67 = 0;
  if ( dword_30861C10 ) {

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 4
支持
分享
最新回复 (5)
雪    币: 12125
活跃值: (10424)
能力值: ( LV13,RANK:660 )
在线值:
发帖
回帖
粉丝
2

上传附件一直没成功,findjmp.exe请自行下载
https://www.aliyundrive.com/s/BP6KnR51awb

最后于 2021-9-2 16:42 被LarryS编辑 ,原因: 拼写错误
2021-9-2 16:41
0
雪    币: 259
活跃值: (1160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3

学废了学废了

最后于 2022-12-27 22:15 被深夜幻想家编辑 ,原因:
2022-12-27 22:12
0
雪    币: 259
活跃值: (1160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主你的pyOffice.py脚本在哪找的,方便分享一下吗?
2022-12-27 22:21
0
雪    币: 12125
活跃值: (10424)
能力值: ( LV13,RANK:660 )
在线值:
发帖
回帖
粉丝
5
深夜幻想家 楼主你的pyOffice.py脚本在哪找的,方便分享一下吗?
这个在 github 上搜索 pyOffice.py 就能找到
2023-1-5 18:52
0
雪    币: 259
活跃值: (1160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
LarryS 这个在 github 上搜索 pyOffice.py 就能找到
okok,感谢
2023-1-17 20:59
0
游客
登录 | 注册 方可回帖
返回
//