火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cnIDAProAppcall功能浅析By:obaby其实IDA的这个功能应该出现的比较早了,最早应该是在IDAPro5.
6中出现的,但是在国内一直没有看到这方面的相关文章.
也不知道国内有没有人留意这些者脚本直接调用内置的函数没有明显的区别.
如果你使用过GDB调试器(Call命令)、VS(Immediate窗口)或者BorlandC++Builder等你应该对于这个功能比较熟悉了.
上面的截图显示了如何使用IDC语法调用了三个函数:printf,MessageBoxA和GetDesktopWindow.
在深入之前,请首先明白一点,本文只是一个简单的介绍,更全面的文章将在后面介绍.
快速开始在开始之前首先要明白使用IDC命令调用Appcall的时候所接受的参数.
上面的函数可以通过下面的简单代码进行调用:火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn就像你看到的那样我们直接引用Appcall函数_prinft就像它是内置的IDC函数一样.
如果你的函数名称中存在在IDC语法中不能用作标记函数名称的字符或者函数名称存在重复,如下图所示:则可以通过下面的IDC语法来调用Appcall:我们使用LocByName函数通过传入函数的名称来获取函数的地址(该地址是可以被调用的).
上面的代码同样可以通过下面的多行代码来实现同样的效果:automyfunc=LocByName("_my_func@8");myfunc("hello","world");需要注意Appcall只在当前进程空间中有效,如果你想在另外的一个进程中执行,那么首先要切换到目标进程中.
Appcall和IDCAppcall机制可以通过下面的函数在IDC中进行调用://Callapplicationfunction//ea-addresstocall//type-typeofthefunctiontocall.
canbespecifiedas://-declarationstring.
example:"intfunc(void);"//-typeinfoobject.
example:GetTinfo(ea)//-zero:thetypewillberetrievedfromtheidbargumentsofthefunctiontocall//Returns:theresultofthefunctioncall//Ifthecallfailsbecauseofanaccessviolationorotherexception,//aruntimeerrorwillbegenerated(itcanbecaughtwithtry/catch)火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn//Infactthereisrarelyanyneedtocallthisfunctionexplicitly.
//IDCtriestoresolveanyunknownfunctionnameusingtheapplicationlabels//andinthecaseofsuccess,willcallthefunction.
Forexample://_printf("hello\n")//willcalltheapplicationfunction_printfprovidedthatthereis//noIDCfunctionwiththesamename.
anyvalueAppcall(ea,type,.
.
.
);AppcallIDC函数需要你传递一个函数的地址,函数类型信息和参数(如果有).
autop=LocByName("_printf");autoret=Appcall(p,GetTinfo(p),"Hello%s\n","world");现在我们已经知道如何来调用一个已经知道函数类型的函数,现在假设有另外的一个函数我们不知道函数类型以及参数类型:在使用Appcall()调用这个函数之前,我们首先需要知道函数类型信息(保存在一个类型信息结构中),autop=ParseType("long__stdcallFindWindow(constchar*cls,constchar*wndname)",0);Appcall(LocByName("user32_FindWindowA"),p,0,"Untitled-Notepad");在这里我们使用ParseType()函数来构建一个类型信息结构体来传递给Appcall()函数,然而永久的设定一个函数的原型也是可能的,因而可以通过下面的代码来设定一个函数的原型:SetType(LocByName("user32_FindWindowA"),"long__stdcallFindWindow(constchar*cls,onstchar*wndname)");通过引用传递参数(Passingargumentsbyreference)为了通过引用传递参数,只需要使用C语言中的&符号进行即可.
例如调用下面的函数:voidref1(int*a){if(a==NULL)return;into=*a;intn=o+1;*a=n;火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cnprintf("calledwith%dandreturning%d\n",o,n);}我们可以在IDC中使用下面的代码实现:autoa=5;Message("a=%d",a);ref1(&a);Message(",afterthecall=%d\n",a);调用一个携带了一个字符串参数并且进行修改的函数:/*Ccode*/intref2(char*buf){if(buf==NULL)return-1;printf("calledwith:%s\n",buf);char*p=buf+strlen(buf);*p+*p='\0';printf("returnedwith:%s\n",buf);intn=0;for(;p!
=buf;p--)n+=*p;returnn;}我们需要创建一个缓冲区并且将它传递给被调用的函数,因为代码如下所示:autos=strfill('\x00',20);//createabufferof20characterss[0:5]="hello";//initializethebufferref2(&s);//callthefunctionandpassthestringbyreferenceif(s[5]Message("notdot\n");elseMessage("dot\n");__usercall调用约定Appcall函数可能没有一个标准的调用约定,例如由汇编语言编写的子函数可能需要通过各种寄存器来传递参数等等.
一种方法是通过_usercall调用约定来描述你的函数:参考如下的函数原型:/*Ccode*///eax=esi-ediint__declspec(naked)asm1()火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn{__asm{moveax,esisubeax,ediret}}从IDC函数中调用将会是下面的代码:autop=ParseType("int__usercallasm1(inta,intb);",0);autor=Appcall(LocByName("_asm1"),p,5,2);Message("Theresultis:%d\n",r);不定参数函数(Variableargumentfunctions)C代码:intva_altsum(intn1,.
.
.
){va_listva;va_start(va,n1);intr=n1;intalt=1;while((n1=va_arg(va,int))!
=0){r+=n1*alt;alt*=-1;}va_end(va);returnr;}IDC代码:autoresult=va_altsum(5,4,2,1,6,9,0);调用函数可能引发异常在使用Appcall的过程中可能会触发异常.
为了捕获这些异常你可以在IDC程序中使用try/catch结构:autoe;try{AppCall(some_func_addr,func_type,arg1,arg2);//Orequally:火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn//some_func_name(arg1,arg2);}catch(e){//Exceptionoccured.
.
.
.
.
}异常结构"e"将会包含如下的数据区段:描述(description):在调试器执行Appcall的过程中产生的异常描述信息;函数(func):发生异常的IDC函数的名称;行号(line):在脚本程序中发生错误行的行号;错误编号(qerrno):最后一个错误的内部编号.
例如你可能会得到如下的信息:description:"Appcall:Theinstructionat0x401F93referencedmemoryat0x5.
Thememorycouldnotberead"file:""func:"___idc0"line:4qerrno:92在一些条件下异常结构有可能会包含更多的信息.
Appcall选项简介Appcall可以功过SetAppcallOptions()函数进行设置,该函数包含如下的选项:APPCALL_MANUAL:仅设置Appcall而不运行(在完成之后你需要调用CleanupAppcall()函数).
可以通过ManualAppcall章节来获取更多信息;APPCALL_DEBEV:如果该标志位被设置,那么在执行appcall的过程中如果有异常产生则会包含异常的全部信息.
可以通过不过调试异常章节来得到更多的信息.
在实际的过程中可以比较方便的恢复Appcall的默认设置,你可以修改它们,然后在把他们修改回来.
为了恢复设置只需要简单的调用GetAppcallOptions()函数即可.
需要注意Appcall选项是保存在数据库中的,所以一旦你修改了他们,当再次运行的时候Appcall选项将会自动恢复ManualAppcall到这里我们已经看到了如何来调用Appcall并且使用脚本来获取执行后的结果,那么如果我们只是想设置环境并且向手工执行函数该怎么办火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn此时就要用到ManualAppcall功能了.
ManualAppcall架构可以用来保存当前执行代码的上下文,然后在另外的空间中执行另外的一个函数.
在执行完成之后我们可以返回到原来的进程空间并且继续从刚才保存的地点继续调试.
让我们以现实中的需求来说明这个功能的意义:1.
你正在调试你的程序2.
你发现了一个存在bug的函数(foo()),当传入特定的参数的时候这个函数会表现的十分怪异foo(0xdeadbeef)3.
那么我们此时是不是应该继续等待一个特殊的参数来继续触发这个问题函数其实没有必要那么复杂,我们只需要手工调用foo函数并且传入特定参数进行跟踪即可.
4.
最后,在执行完成之后只需要执行CleanupAppcall()来恢复手工调用appcall之前异常的内容即可为了验证效果我们以上文中提到的ref1函数来进行试验,我们只需要传入一个非法的指针即可:1.
SetAppcallOptions(APPCALL_MANUAL);//SetmanualAppcallmode2.
ref1(6);//callthefunctionwithaninvalidpointer在执行完上面的代码之后IDA将会转换到调用的函数,到这里我们就可以进行调试了.
在执行到函数末尾的时候代码如下:在执行到函数返回之后我们很可能会看到如下的代码:这是我们用来检测Appcall函数末尾的控制代码.
到这里我们就可以调用CleanupAppcall()来返回到上一次执行的上下文空间了.
火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cn捕获调试异常在上文中我们已经可以捕获Appcall调用过程中的异常,但是如果我们想要知道操作系统原生的异常信息这些是远远不够的.
如果我们多多少少的能够从调试器模块中获取到最后的debug_event_t指令就更好了.
APPCALL_DEBEV选项使得我们的想法成为可能.
我们通过APPCALL_DEBEV选项再次来重复上面的例子:autoe;try{SetAppcallOptions(APPCALL_DEBEV);//Enabledebugeventcapturingref1(6);}catch(e){//Exceptionoccured.
Thistime"e"ispopulatedwithdebug_event_tfields(checkidd.
hpp)}在这种情况下,如果我们转存异常结构信息,我们将会得到下面的属性:can_cont:1code:C0000005hea:401F93heid:40h(fromidd.
hpp:EXCEPTION=0x00000040Exception)file:""func:"___idc0"handled:1info:"Theinstructionat0x401F93referencedmemoryat0x6.
Thememorycouldnotberead"line:4hpid:123Chref:6htid:1164hAppcall和PythonAppcall的概念和IDC与Python基本是一致的,然而Appcall/Python有着不同的语法,(不同的引用,宽字符等等).
火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cnAppcall构架是由idaapi模块提供的,调用一个Appcall:Appcall.
printf("Helloworld!
\n");同样可以创建一个Appcall函数的引用并且直接调用:printf=Appcall.
printf#.
.
.
later.
.
.
printf("Helloworld!
\n");如果你的函数包含在Python中不能用作名称的字符或者存在冲突那么可以通过下面的代码进行调用:findclose=Appcall["__imp__FindClose@4"]getlasterror=Appcall["__imp__GetLastError@0"]setcurdir=Appcall["__imp__SetCurrentDirectoryA@4"]如果你想重新定义已经存在的函数的定义则可以通过调用Appcall.
proto(func_name、func_ea、prototype_string)来实现:#passanaddressnameandAppcall.
proto()willresolveitloadlib=Appcall.
proto("__imp__LoadLibraryA@4","int(__stdcall*LoadLibraryA)(constchar*lpLibFileName);")#PassanEAinsteadofanamefreelib=Appcall.
proto(LocByName("__imp__FreeLibrary@4"),"int(__stdcall*FreeLibrary)(inthLibModule);")为了传递Unicode字符串你需要用到Appcall.
unicode()函数:getmodulehandlew=Appcall.
proto("__imp__GetModuleHandleW@4","int(__stdcall*GetModuleHandleW)(LPCWSTRlpModuleName);")hmod=getmodulehandlew(Appcall.
unicode("kernel32.
dll"))定义一个函数然后关联到一个地址你同样可以得到一个Appcall:#Createatypedobject(noaddressisassociatedyet)virtualalloc=Appcall.
typedobj("int__stdcallVirtualAlloc(intlpAddress,SIZE_TdwSize,DWORDflAllocationType,DWORDflProtect);")#Laterwehaveanaddress,sowepassit:virtualalloc.
ea=LocByName("kernel32_VirtualAlloc")#NowwecanAppcall:ptr=virtualalloc(0,Appcall.
Consts.
MEM_COMMIT,0x1000,Appcall.
Consts.
PAGE_EXECUTE_READWRITE)在我们得出结论之前(如果你已经认真的读过上面的内容),这里提供了一个小脚本,它可以用来初始化和终止Appcall通过快捷键.
如果你想每次都让脚本自动加载那么就将这个脚本写入到idc\ida.
idc文件中即可:#includeexternlast_cmd,last_opt;火星信息安全研究院By:obabyhttp://www.
h4ck.
org.
cnstaticAppcall_Here(){last_opt=GetAppcallOptions();SetAppcallOptions(APPCALL_MANUAL);autot,h;t=ParseType("voidx(void);",0);h=here;Appcall(FirstSeg(),t);SetAppcallOptions(last_opt);Eip=h;}staticAppcall_Start(){autos=AskStr(last_cmd,"EnterAppcall");if(s=="")return;last_cmd=s;last_opt=GetAppcallOptions();SetAppcallOptions(APPCALL_MANUAL);Message(">%s原代码处.
Appcall能做的事情远比在本文中提到的要多的多,写这篇文章主要是想抛砖引玉,如果大家有什么好的技术还希望能一起交流,欢迎评论.
企鹅小屋:垃圾服务商有跑路风险!企鹅不允许你二次工单的,二次提交工单直接关服务器,再严重就封号,意思是你提交工单要小心,别因为提交工单被干了账号!前段时间,就有站长说企鹅小屋要跑路了,站长不太相信,本站平台已经为企鹅小屋推荐了几千元的业绩,CPS返利达182.67CNY。然后,站长通过企鹅小屋后台申请提现,提现申请至今已经有20几天,企鹅小屋也没有转账。然后,搞笑的一幕出现了:平台账号登录不上提示...
A400互联怎么样?A400互联是一家成立于2020年的商家,A400互联是云服务器网(yuntue.com)首次发布的云主机商家。本次A400互联给大家带来的是,全新上线的香港节点,cmi+cn2线路,全场香港产品7折优惠,优惠码0711,A400互联,只为给你提供更快,更稳,更实惠的套餐,香港节点上线cn2+cmi线路云服务器,37.8元/季/1H/1G/10M/300G,云上日子,你我共享。...
现在宝塔面板真的是越来越过分了,删除文件、删除数据库、删除站点等操作都需要做计算题!我今天升级到7.7版本,发现删除数据库竟然还加了几秒的延时等待,也无法跳过!宝塔的老板该不会是小学数学老师吧,那么喜欢让我们做计算题!因此我写了个js用于去除各种计算题以及延时等待,同时还去除了软件列表页面的bt企业版广告。只需要执行以下命令即可一键完成!复制以下命令在SSH界面执行:Layout_file="/w...
原代码为你推荐
硬盘的工作原理硬盘的工作原理是?(不要给我网址,我用的手机)梦之队官网NBA梦之队是什么游戏?百度关键词工具常见的关键词挖掘工具有哪些www.522av.com我的IE浏览器一打开就是这个网站http://www.522dh.com/?mu怎么改成百度啊 怎么用注册表改啊sss17.com一玩棋牌吧(www.17wqp.com)怎么样?51sese.com谁有免费电影网站www.gegeshe.comSHE个人资料m.2828dy.comwww.dy6868.com这个电影网怎么样?33tutu.com33gan.com改成什么了www.javlibrary.com跪求一个JAVHD.com的帐号
备案域名 免费申请网站域名 中国万网虚拟主机 中国域名交易中心 万网域名证书查询 budgetvm 80vps 主机点评 美国主机评论 namecheap 163网 轻博 777te 蜗牛魔方 上海域名 东莞服务器 国外ip加速器 多线空间 常州联通宽带 贵阳电信 更多