windbg调试从二进制漏洞分析入门到辅助分析脚本诞生
Firstchanceexceptionsarereportedbeforeanyexceptionhandling.Thiceptionmaybeexpectedandhandled.
41414141
Target[5]=fgetc(hFile);
}
if(dword_443540(result=dword_443548,dword_443548))
在windbg中,涉及到寄存器操作的都需要加上r,而涉及到一些if,else,while命令的,则需要加上一个“.”,windbg有很多种调用脚本的方法,这里介绍
.if(@eip==$t1)
idapro直接观察打开pe文件开头就可以获得
PCManFTPD2+0x29db:
冲区,而没有进行长度控制的情况下,会造成缓冲区溢出。
41414141
ff154c554300
004029d5
}
dword
比起windbg的脚本,idapro提供了一套自己的功能,在代码编写方面和C很像,需要通过#include方法,把idc提供的api库导入,这样才能使用ida可识
ss=0023ds=0023es=0023fs=003bgs=0000
nvupei
iopl=0
GetLocalTime(SystemTime);v4=*((_DWORD*)v2+9);if(v4)
fseek(hFile,37,1);
Target[3]=fgetc(hFile);
eip=004029d5esp=0012edacebp=00a61ba0
cs=001b
eax=00000886ebx=00000000ecx=001694d8edx=0012edc4esi=00000000edi=00000402
push
autoi,temp;
//
temp=temp-windbg_image_base_addr+ida_image_base_addr;SetColor(temp,1,0x98fb98);
41414141
0012edd4
41414141
$$a
(四)写在最后
(三)idahelp.和winidc.idc
Target[7]=fgetc(hFile);
{
Target[2]=fgetc(hFile);
PCManFTPD2+0x29df:
%d/%d/%d[%02d:%02d](%05d)%s%s\r\n,SystemTime.wYear,
(d4.220):Accessviolation-codec0000005(firstchance)
eax=00000886ebx=00000000ecx=001694d8edx=7c92e4f4esi=00000000edi=00000402
AAAAAAAAAAAAAAAA
0012edc4
Target[4]=fgetc(hFile);
设置首页-搜狗输入法-支付中心-搜狐招聘-广告服务-客服中心-联系方式-隐私权-AboutSOHU-公司介绍-网站地图-全部新闻-全部博文
.break
}
}
0012ee14
通过kb命令,我们可以看到在程序执行到崩溃场景前调用的函数内容,而这个调用往往是嵌套调用,就是栈增长方向是外层函数,因为熟悉堆栈的小伙伴应该知道,栈的开辟是由高地址向低地址开辟,堆是由低地址向高地址开辟,也就是每次调用内层函数的时候,栈就会向低地址方向开辟一片空间使用,我们可以这样简单理解函数调用关系。
2016-08-1716:50:00红黑联盟论坛(一)写在前面
41414141
nc
efl=00010212
efl=00000202
造成软件或者系统崩溃的原因有很多,比如某些关键地址,关键指针被覆盖,导致引用时发生错误,比如空指针引用,比如越界操作内存等等,而二进制漏洞分析就是要分析为什么会造成崩溃的发生,这样无论对于修补漏洞,还是编写利用工具,都有极大的帮助。
offsetPCManFTPD2+0x411dc(004411dc)
jQuery8586489856_30
004029df
41414141
nvupeiplnzacponc
.printfeip:0x%.08x\n,@eip;
41414141
004029db
41414141
我们在使用idapro脚本进行标记。
.printfTryrunwithrightaddress;
{
int__thiscallsub_403E60(void*this,int*a2)
Target[1]=fgetc(hFile);
$$如果再次命中,证明不是最后一次漏洞触发过程
ss=0023ds=0023
#include
efl=00000246
一般当我们第一次开始学习漏洞分析的时候,拿到一个崩溃场景,往往会碰到这样的崩溃场景。
Target[4]=fgetc(hFile);
两种常用的调用方法。
41414120
externida_image_base_addr,windbg_image_base_addr,offset;
0:000p
}
(0043554c)]
eip=41414141esp=0012edb8
.text:00403F6Bretn4
41414141
fseek(hFile,9,1);
.break;
函数调用先后顺序的标记
.if(@eip==$t2)
ss=0023ds=0023es=0023fs=003bgs=0000
cs=001b
eax=0012edc4ebx=00000000ecx=000000fcedx=00a61aa4esi=00000000edi=00000402
.logopenC:\ida.log
{
SystemTime.wHour,
temp=xtol(Target);
temp=xtol(Target);
nvupeiplzrnapenc
PCManFTPD2+0x29d5:
AAAAAAAAAAAAAAAA
{
for(i=1;i
这样,就完成了对这个指令区间的,接下来我们来看一下winidc.idc。
.printfeip:0x%.08x\n,@eip;t
这就需要我们利用脚本对想的地址区间进行设定,然后脚本会不断,同时通过logopen命令来将整个时的径保存至一个文件里,方便之后
在漏洞分析过程中,避免不了这样一个过程----回溯。刚才提到,漏洞分析就是要分析为什么会造成崩溃的发生,那么就少不了对程序执行流程的回溯,通常在windbg中,我们使用“kb”命令回溯堆栈调用的情况。
cs=001b
}
68dc114400
eax=00000000ebx=00000000ecx=00000000edx=0000000cesi=0012edc4edi=00000004
{
说到二进制漏洞分析,在windows下,入门阶段最好用的两款工具就是windbg和IDApro对于这两款工具,网上相关的介绍有很多,这里我就不再多做赘述,在我进行漏洞分析的过程中,经常用的方法就是windbg的动态调试,配合上IDApro的静态分析,其中windbg提供了很强大的动态调试功能,包括堆栈的回溯,,加载符号表中特定的变量,结构体等等;而idapro则提供了静态分析的功能,比如指令流流程,伪代码还原等等。
0012ede4
ptr[PCManFTPD2+0x3554c
$$如果命中最后结束地址
//主函数staticmain(void)
(三)从PcManFTP漏洞看辅助分析脚本
这里AskStr是获取用户输入字符串,AskFile则是获取用户文件,这里打开的文件,就是刚才我们通过windbg脚本生成的文件ida.log,之后通过fseek的方法跳转到指令开头部分,随后会获取相应的地址,并且进行标记,同时需要用户输入ida的对应领空基址以及windbg对应领空基址,这是为了对抗aslr。
eip=004029dfesp=0012edbcebp=00a61ba0iopl=0
SystemTime.wMinute,*((_DWORD*)v2+3),v5,
别的脚本函数,来完成我们的功能。来看一下winidc.idc的代码。
.while(1)
41414141
void*v2;//;//;//eax@3
AAAAAAAAAAAAAAAA
Target[7]=fgetc(hFile);
从接触二进制漏洞以来一直在边学边思考,有没有一些共通的地方,可以通过一些简单的脚本或者工具来简化一些过程,不得不承认二进制漏洞无论在挖掘,分析,还是最后写exp上都是有一定难度的,经过不断的请教,大牛们的作品,也逐渐摸到了一些门道,下面的分享如有不当之处请多多指教,大牛轻喷:)
可以看到,执已经被标记出来了,再看一程图。
ss=0023ds=0023es=0023fs=003bgs=0000
我们需要在ida中动态这个调试过程,追踪从接收到PoC中的畸形数据,到触发漏洞的整个过程,才能较为完整的完成对漏洞的分析,那么实际上在一个函数内部,涉及到大量的条件判断,跳转等功能,在ida的指令流程图中可以看出这个过程在静态分析中,会耗去很多时间。
0012ee04
{
地址有效性的判断
其他可能存在的bug
$$启始地址必须是当前命中的地址
FileLength=filelength(hFile)-30-34;Fileline=FileLength/17;
0:000p
r@$t4=@eip
.else
在004029d5接收到recv之后,观察一下此时接收到的数据。
AAAAAAAAAAAAAAAA
FileName=AskFile(0,*.*,PleasechooseWindbgInstructionstreamfile);hFile=fopen(FileName,r+);
//获取输入Windbg和IDA中模块的基址
41414141
v5=*((_DWORD*)v2+1);
v5=*(_DWORD*)(v4+8);else
lea
第一种调用的是不带参数的,第二种则是调用带参数的,在我的脚本里,需要两个参数,在脚本开头已经传入t1,t2模拟寄存器里。
.printfeip:0x%.08x\n,@eip;t$$开始
intv5;//;//;//;//ct_SYSTEMTIMESystemTime;//[sp+8h][bp-814h]@3DWORDNumberOfBytesWritten;//[sp+18h][bp-804h]@7charBuffer;//[sp+1Ch][bp-800h]@6
.else
这两个参数分别对应脚本执行的起始地址和结束地址,在上述的分析过程中,我们提到在回溯调用的过程中,需要由外层函数向内层函数不断动态,
这里我以PcManFTP这个漏洞为例,先结合漏洞的分析过程,再辅助分析脚本的编写及功能,首先这个漏洞是由于PcManFTP在对用户传输的数据进行处理的过程中,没有对传输的内容进行长度控制和内容检查,从而导致可以通过ftp指令+畸形字符串来覆盖返回地址,最后导致远程代码执行,在发送PoC之后,这边用windbg对进程进行附加,可以捕获到崩溃场景。
在ida的文件菜单中有一个功能叫command,可以导入这个idc的脚本。
ABORAAAAAAAAAAA
41414141
es=0023fs=003bgs=0000
已经是畸形字符串了,接下来进行连续。我们到一处函数sub_403E60,这处函数中会执行一处sprintf操作,正是这个过程会将payload拷贝到缓
Target[2]=fgetc(hFile);
在windbg下,支持使用脚本,同样在idapro下,也支持使用.idc的脚本,首先我来一下windbg下的脚本,以及编写,首先来看一下idahelp.。
{
.if(@$t4!=$t1)
0:000gBreakpoint0hit
Target[6]=fgetc(hFile);
edx,[esp+8]
AAAAAAAAAAAAAAAA
524f4241
Target[1]=fgetc(hFile);
.echohelloworld
执行脚本之后,程序会按照流程动态执行,并且将整个执行的过程记录在txt中。
41414141
call
{
41414141
plnznapo
temp=temp-windbg_image_base_addr+ida_image_base_addr;SetColor(temp,1,0x98fb98);
.logcloseC:\log.txt
(二)为什么要写辅助分析脚本
r@$t1=${$arg1}r@$t2=${$arg2}r@$t3=@esp
那么实际上,我写的这个辅助分析脚本,其实也是为了针对这种情况而诞生的。
Target[6]=fgetc(hFile);
Target[0]=fgetc(hFile);
41414141
41414141
41414141
41414141
eip=004029dbesp=0012edbcebp=00a61ba0iopl=0
{
.printfThisisnotthelasttunnel\n;
41414141
ebp=00a61b40iopl=0
感谢蛙师傅给予的灵感!
在对这个过程进行动态调试的过程中,涉及到很多函数的嵌套调用,以及很多的跳转,这无论在windbg还是idapro中通过地址比对来动静结合是很耗时间的,因为要经过很多的地址比对,甚至有时在面对ASLR的情况下还需要进行地址换算,于是就有了这个辅助分析脚本。
v2=this;
41414141
{
相应的脚本也已经开源放在我的github下,欢迎大家多提意见,也可以进行修改,后续我也会根据我逐步学习逐步改进增强工具的功能。这里之所以说是辅助分析工具,是因为我还想不到一种方法能够完全自动化分析漏洞的成因,只能说简化一些漏洞分析过程中的过程。
$$纪录第一次并跳过
对应函数的执也都很清晰的展示出来,省去了对地址比对分析的过程。
nvupeiplzrnapenc
SystemTime.wDay,
SystemTime.wMonth,
edx
通过回溯,我们找到了一处callrecv的调用,这个调用会获取畸形的payload。
$$
最后执行到返回后会因为返回地址被覆盖导致任意代码执行。
}
Target[0]=fgetc(hFile);
}
temp=AskStr(00401000,PleaseinputIDAsimageBase,Forexample:);ida_image_base_addr=xtol(temp);
v6=sprintf(Buffer,
搜狐不良信息举报邮箱:
//
这里我和大家分享了二进制漏洞分析入门的一些技巧方法,并且结合一个实例漏洞分享了我写的辅助分析脚本,比较基础,希望能对大家有所帮助,这个辅助分析脚本也存在一定的不足,以后会继续完善升级功能,并且弥补存在的一些bug。
在二进制漏洞的入门学习中,我个人感觉相比漏洞挖掘,构造PoC,编写Exp,只有漏洞分析是最核心也是最容易入手的,通过已有的PoC,搭建复现漏洞的,获得存在漏洞的软件,复现漏洞后就可以进行分析了,而我写的这个脚本,也是为了简化一些漏洞分析过程,从而更清晰直观的看到漏洞执行流程。
cs=001b
temp=AskStr(00401000,PleaseinputWindbgsimageBase,Forexample:);windbg_image_base_addr=xtol(temp);
8d542408
ds:0023:0043554c={WSOCK32!recv(71a42e70)}
0:000dc
通过import按钮导入idc脚本,再通过run执行,进行相应的设置,这里我们选择打开之前windbg生成的文件。进行对应的参数设置之后观察一下效果。
41414141
Target[3]=fgetc(hFile);
a2);
41414141
41414141
autoFileName,FileLength,hFile,str,Target=66666666;autoFileline;
efl=00000246
Target[5]=fgetc(hFile);
两者获取基址的方法,windbg通过lm命令查看加载模块获得基址。
???
0012edf4