函数原代码

原代码  时间:2021-03-17  阅读:()
火星信息安全研究院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能做的事情远比在本文中提到的要多的多,写这篇文章主要是想抛砖引玉,如果大家有什么好的技术还希望能一起交流,欢迎评论.

阿里云秋季促销活动 轻量云服务器2G5M配置新购年60元

已经有一段时间没有分享阿里云服务商的促销活动,主要原因在于他们以前的促销都仅限新用户,而且我们大部分人都已经有过账户基本上促销活动和我们无缘。即便老用户可选新产品购买,也是比较配置较高的,所以就懒得分享。这不看到有阿里云金秋活动,有不错的促销活动可以允许产品新购。即便我们是老用户,但是比如你没有购买过他们轻量服务器,也是可以享受优惠活动的。这次轻量服务器在金秋活动中力度折扣比较大,2G5M配置年付...

DMIT(季度$28.88)调整洛杉矶CN2 GIA优化端口

对于DMIT商家已经关注有一些时候,看到不少的隔壁朋友们都有分享到,但是这篇还是我第一次分享这个服务商。根据看介绍,DMIT是一家成立于2017年的美国商家,据说是由几位留美学生创立的,数据中心位于香港、伯力G-Core和洛杉矶,主打香港CN2直连云服务器、美国CN2直连云服务器产品。最近看到DMIT商家有对洛杉矶CN2 GIA VPS端口进行了升级,不过价格没有变化,依然是季付28.88美元起。...

NameCheap新注册.COM域名$5.98

随着自媒体和短视频的发展,确实对于传统的PC独立网站影响比较大的。我们可以看到云服务器商家的各种促销折扣活动,我们也看到传统域名商的轮番新注册和转入的促销,到现在这个状态已经不能说这些商家的为用户考虑,而是在不断的抢夺同行的客户。我们看到Namecheap商家新注册域名和转入活动一个接一个。如果我们有需要新注册.COM域名的,只需要5.98美元。优惠码:NEWCOM598。同时有赠送2个月免费域名...

原代码为你推荐
johncusack约翰·库萨克好看的的恐怖片全集硬盘工作原理高人指点:电子存储器(U盘,储存卡,硬盘等)的工作原理安徽汽车网安徽什么汽车网站比较好?李子柒年入1.6亿李子柒男朋友是谁,李子柒父母怎么去世的?同ip网站查询我的两个网站在同一个IP下,没被百度收录,用同IP站点查询工具查询时也找不到我的网站,是何原因?原代码什么叫源代码,源代码有什么作用曲妙玲张婉悠香艳版《白蛇传》是电影还是写真集?同ip站点同IP做同类站好吗?www.zjs.com.cn我的信用卡已经申请成功了,显示正在寄卡,怎么查询寄卡信息?partnersonline国内有哪些知名的ACCA培训机构
ip反查域名 vps服务器 ftp空间 主机评测 directspace dreamhost 免备案cdn 12306抢票攻略 mobaxterm 本网站在美国维护 免费个人空间申请 193邮箱 165邮箱 admit的用法 789电视剧 空间登陆首页 个人免费邮箱 广州虚拟主机 iki 测试网速命令 更多