3.1 IDA Pro编写IDC脚本入门

IDA Pro内置的IDC脚本语言是一种灵活的、C语言风格的脚本语言,旨在帮助逆向工程师更轻松地进行反汇编和静态分析。IDC脚本语言支持变量、表达式、循环、分支、函数等C语言中的常见语法结构,并且还提供了许多特定于反汇编和静态分析的函数和操作符。由于其灵活性和可扩展性,许多逆向工程师都喜欢使用IDC脚本语言来自动化反汇编和静态分析过程,以提高效率和准确性。

在IDA中如果读者按下Shift + F2则可调出脚本编辑器,如下图所示,其中左侧代表当前脚本的名称列表,右侧则代表脚本的具体实现细节,底部存在三个菜单,第一个按钮是运行脚本,第二个按钮是覆盖导入脚本,第三个则是追加导入,他们之间的功能个有不同,读者可自行体会;

3.1.1 IF语句的构建

IF语句的使用非常容易,如下代码,通过ScreenEA()函数识别到当前光标所在位置处的指令内存地址,并对比该内存地址是否符合特定的条件,如果符合则输出,不符合则最终输出没有找到;

#include <idc.idc>static main()
{auto CurrAddress = ScreenEA(); if(CurrAddress == 0x0046E31A){Message("程序OEP => 0x%x \n",CurrAddress);}else if(CurrAddress == 0x0046E331){Message("程序OEP => 0x%x \n",CurrAddress);}else{Message("没有扎到OEP \n");}
}

3.1.2 FOR语句的构建

与C语言格式几乎一致,For语句的构建也很容易理解,首先程序通过GetFunctionAttr()函数并设置FUNCATTR_START属性获取到当前光标所指向程序段的开始地址,通过FUNCATTR_END设置光标的结束位置,最后调用For循环,一次输出当前内存地址及下一个内存地址,直到将本段内容全部输出为止;

#include <idc.idc>static main()
{auto origEA,currEA,funcStart,funcEnd;origEA = ScreenEA();// origEA = OEP 如果origEA 不在函数内则返回-1funcStart = GetFunctionAttr(origEA,FUNCATTR_START);funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);Message("OEP: %x 起始地址: %x --> 结束地址: %x \n",origEA,funcStart,funcEnd);// NextHead 在currEA开始的位置寻找下一条指令的地址for(currEA = funcStart; currEA != -1; currEA=NextHead(currEA,funcEnd)){Message("指令地址:%8x \n",currEA);}
}

3.1.3 WHILE语句的构建

该语句的构建与FOR语句基本一致,与FOR语句唯一的不同在于该语句只能接受一个参数,如下代码中读者需要注意GetFunctionName()可用于获取当前光标所在位置处所属函数的名称。

#include <idc.idc>static main()
{auto origEA,currEA,funcStart,funcEnd;origEA = ScreenEA();// origEA = OEP 如果origEA 不在函数内则返回-1funcStart = GetFunctionAttr(origEA,FUNCATTR_START);funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);Message("OEP: %x 起始地址: %x --> 结束地址: %x \n",origEA,funcStart,funcEnd);while(currEA != BADADDR){Message("--> %x name: %s \n",currEA,GetFunctionName(currEA));currEA = NextHead(currEA,funcEnd);}
}

3.1.4 函数的实现

IDA中使用函数通常可在一个字符串之前定义为static,函数的参数列表一般而言是以逗号进行间隔开的,当函数存在返回值是则通过return语句返回。

#include <idc.idc>// 定义一个函数
static OutPutAddress(MyString)
{auto currAddress;currAddress = ScreenEA();Message("%d \n",MyString);return currAddress;
}// 传递多个参数
static OutPutAddressB(x,y)
{return x+y;
}static main()
{auto ret = OutPutAddress(123);Message("返回当前地址 = 0x%x \n",ret);auto ref = OutPutAddressB(100,200);Message("计算数值 = %d \n",ref);}

3.1.5 定义并使用数组

与高级语言类似,IDC脚本中同样支持数组操作,不同于C语言中的数组,IDC中在使用时首先需要通过CreateArray("array")创建一个数组,当数组指针被创建成功后下一步则是通过GetArrayId("array")得到该数组的指针,通过指针读者可以使用SetArrayString设置一个字符串变量,或使用SetArrayLong设置整数变量,当用户需要使用变量时则需要通过GetArrayElement()函数对数组内的数据进行提取,提取时AR_STR代表提取字符串,AR_LONG则代表提取整数类型,当读者需要删除数组内的特定元素可使用DelArrayElement()函数,最后使用结束调用DeleteArray()注销整个数组;

#include <idc.idc>static main()
{// 创建数组元素auto array_ptr = CreateArray("array");// 获取数组指针auto ptr = GetArrayId("array");Message("获取到的操作指针: %x \n",ptr);// 设置两个字符串变量SetArrayString(ptr,0,"hello");SetArrayString(ptr,1,"lyshark");// 设置两个整数变量SetArrayLong(ptr,2,100);SetArrayLong(ptr,3,200);// 如果提取字符串使用 AR_STR 标记 ,提取整数使用 AR_LONGauto st = GetArrayElement(AR_STR,ptr,0);auto st1 = GetArrayElement(AR_STR,ptr,1);Message("提取字符串变量: %s %s !\n",st,st1);auto lo = GetArrayElement(AR_LONG,ptr,2);Message("提取整数变量: %d \n",lo);// 删除数组的0号元素DelArrayElement(AR_STR,ptr,0);// 注销整个数组DeleteArray(ptr);
}

3.1.6 字符串处理

IDC中读者可以使用form()函数实现对特定字符串的格式化输出操作,IDC中同样也内置了各类转换函数,如下代码所示,则是IDC中可以经常被用到的函数调用,读者可自行参考;

#include <idc.idc>static main()
{// 格式化字符串,类似于sprintfauto name = form("hello %s","lyshark");Message("格式化后的内容: %s \n",name);Message("十六进制转为整数: %d \n",xtol("0x41"));Message("十进制100转为八进制: %d \n",ltoa(100,8));Message("十进制100转换二进制: %d \n",ltoa(100,2));Message("字符A的ASCII: %d \n",ord("A"));Message("计算字符串长度: %d \n",strlen("hello lyshark"));// 在主字符串中寻找子串auto main = "hello lyshark";auto sub = "lyshark";Message("寻找子串: %d \n",strstr(main,sub));
}

3.1.7 枚举所有函数

如下脚本实现了枚举当前指针所在位置处所有函数名称及地址,首先通过ScreenEA()函数获取当前指针所在位置,通过SegStart()用于获取该指针所在位置处模块的开始地址,与之对应的是SegEnd();则用于获取结束地址,接着通过调用GetFunctionName();得到当前地址处的函数名,并依次通过NextFunction();得到下一个模块地址,最终输出所有函数名及其地址信息;

#include <idc.idc>static main()
{auto currAddr,func,endSeg,funcName,counter;currAddr = ScreenEA();func = SegStart(currAddr);endSeg = SegEnd(currAddr);Message("%x --> %x \n",func,endSeg);counter = 0;while(func != BADADDR && func < endSeg){funcName = GetFunctionName(func);if(funcName != " "){Message("%x --> %s \n",func,funcName);counter++;}func = NextFunction(func);}
}

当然读者可以通过增加IF语句来判断funcName函数名是否是我们所需要枚举的,如果是则输出,如果不是则继续下一个函数,依次类推实现函数枚举功能,读者只需要在上述代码基础上稍加改进即可实现;

#include <idc.idc>static main()
{auto currAddr,func,endSeg,funcName,counter;currAddr = ScreenEA();func = SegStart(currAddr);endSeg = SegEnd(currAddr);Message("%x --> %x \n",func,endSeg);counter = 0;while(func != BADADDR && func < endSeg){funcName = GetFunctionName(func);if(funcName != " "){if(funcName == "__lock"){Message("%x --> %s \n",func,funcName);}counter++;}func = NextFunction(func);}
}

3.1.8 设置内存区域标签高亮

标签高亮功能的实现依赖于SetColor函数,该函数传入三个参数,其中参数1用于指定需要检索的范围,该范围可以通过NextHead()函数获取到,只要该节点不会返回BADADDR则可以继续遍历下一个节点,第二个参数则代表标注类型,第三个参数代表要在那个位置进行标注;

#include <idc.idc>static main(void)
{auto head, op;head = NextHead(0x00000000, 0xFFFFFFFF);while ( head != BADADDR ){op = GetMnem(head);Message("%x %s \n",head,op);if ( op == "jmp" || op == "call" )SetColor(head, CIC_ITEM, 0x010187);if (op == "xor")SetColor(head, CIC_ITEM, 0x010198);head = NextHead(head, 0xFFFFFFFF);}
}

3.1.9 地址反汇编输出

在IDA中有时我们需要对特定位置进行反汇编,并以脚本的方式输出,此时读者可使用GetDisasm(inst)函数来实现,该函数传入一个RfirstB生成的迭代类型,并依次循环输出,直到对100行输出为止;

#include <idc.idc>static main(void)
{auto decode = 0x401000;auto xref;for(xref = RfirstB(decode); xref != BADADDR; xref = RnextB(decode,xref)){Message("xref: %x\n",xref);auto i = 0;auto inst = xref;auto op;while((i < 100) ){// 向后枚举下一个inst = FindCode(inst,0x00);// 输出反汇编op = GetDisasm(inst);Message("%x --> %s \n",inst,op);i++;}} 
}

当具备了反汇编功能后,那么读者则可通过各种方式实现对指令集的判断,并以此来实现过滤特定指令地址并输出的目的,如下所示,通过strstr()函数对符合特定条件的字符串进行过滤,当找到后返回该函数的所在位置;

#include <idc.idc>static main()
{auto currAddr,startSeg,endSeg;currAddr = ScreenEA();startSeg = SegStart(currAddr);endSeg = SegEnd(currAddr);Message("OEP = %x 起始地址: %x 结束地址: %x \n",currAddr,startSeg,endSeg);while(startSeg < endSeg){auto op = GetDisasm(startSeg);// 查找第一条指令if(strstr(op,"push    esi")==0){startSeg++;op = GetDisasm(startSeg);if(strstr(op,"push    edi")){Message("特征: %x \n",startSeg-1);}}startSeg++;}
}

当然反汇编函数并非只有GetDisasm读者同样可以使用GetMnem返回位于特定地址处的指令,GetOpnd用于返回特定位置处的机器码,同样可以使用FindBinary实现对特定地址的特征码搜索功能;

#include <idc.idc>static main()
{// 搜索特征码auto code = FindBinary(0x401020,1,"55 8B EC");Message("%x \n",code);// 返回反汇编代码code = GetDisasm(0x401000);Message("%s \n",code);// 返回位于地址处的指令code = GetMnem(0x401000);Message("%s \n",code);// 返回opcode机器码code = GetOpnd(0x401070,0);Message("%s \n",code);
}

3.1.10 枚举函数栈帧

生成每个函数的栈帧,通过NextFunction()函数可实现枚举当前模块内所有函数地址,通过循环并调用GetFram()来得到当前函数栈帧大小,并使用GetMemberOffset()保存栈中返回地址偏移量,依次循环输出当前函数内的完整栈帧数据;

#include <idc.idc>static main()
{auto addr,args,end,locals,frame,firstArg,name,ret;for(addr = NextFunction(addr); addr != BADADDR; addr = NextFunction(addr)){name = Name(addr);end = GetFunctionAttr(addr,FUNCATTR_END);locals = GetFunctionAttr(addr,FUNCATTR_FRSIZE);// 得到栈帧大小frame = GetFrame(addr);// 栈中保存返回地址偏移量ret = GetMemberOffset(frame," r");if(ret == -1){continue;}firstArg = ret +4;args = GetStrucSize(frame) - firstArg;Message("函数: %s 开始: 0x%x 结束: 0x%x 大小: %d bytes 栈帧: %d bytes (%d args) \n",name,addr,end,locals,args,args/4);}
}

3.1.11 检索交叉引用

枚举当前模块中的交叉引用,通过XrefType()函数可枚举出当前被分析程序中的交叉引用情况,如下案例中实现了对当前程序内所有交叉引用的枚举工作,并输出三个参数,参数1代表主函数,参数2代表被引用函数,参数3代表当前函数的内存地址;

#include <idc.idc>static main()
{auto func,end,target,inst,name,flags,xref;flags = SEARCH_DOWN | SEARCH_NEXT;func = GetFunctionAttr(ScreenEA(),FUNCATTR_START);if(func != -1){name =Name(func);end = GetFunctionAttr(func,FUNCATTR_END);for(inst = func;inst < end; inst = FindCode(inst,flags)){for(target = Rfirst(inst);target != BADADDR; target = Rnext(inst,target)){xref = XrefType();if(xref == fl_CN || xref == fl_CF){Message("%s | %s | %x \n",name,Name(target),inst);}}}}
}

如果读者想要实现枚举特定一个函数的交叉引用信息,则可通过使用LocByName(bad_func)增加过滤条件,并依次实现过滤特定函数的目的,代码的修改只需要小改即可;

#include <idc.idc>static FindFunction(bad_func)
{auto func,addr,xref,source;func = LocByName(bad_func);if(func == BADADDR){Message("error \n");}else{for(addr = RfirstB(func);addr != BADADDR; addr = RnextB(func,addr)){xref = XrefType();if(xref == fl_CN || xref == fl_CF){source = GetFunctionName(addr);Message("%s call => %0x in %s \n",bad_func,addr,source);}}}  
}static main()
{FindFunction("LoadString");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/138047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker学习——⑥

文章目录 1、什么是存储卷?2、为什么需要存储卷?3、存储卷分类4、管理卷 Volume5、绑定卷 bind mount6、临时卷 tmpfs7、综合实战-MySQL 灾难恢复8、常见问题 1、什么是存储卷? 存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立…

AI 引擎系列 5 - 以 AI 引擎模型为目标运行 AI 引擎编译器(2022.1 更新)

AI 引擎系列 5 - 以 AI 引擎模型为目标运行 AI 引擎编译器&#xff08;2022.1 更新&#xff09; 简介 在先前的 AI 引擎系列博文中&#xff0c;我们以 x86 模型为目标运行了 AI 引擎编译器&#xff0c;并运行了 X86 仿真器来验证 AI 引擎应用的功能模型。在本文中&#xff0c;…

2011年09月21日 Go生态洞察:Go图像处理包

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Javaweb之javascript的BOM对象的详细解析

1.5.2 BOM对象 接下来我们学习BOM对象&#xff0c;BOM的全称是Browser Object Model,翻译过来是浏览器对象模型。也就是JavaScript将浏览器的各个组成部分封装成了对象。我们要操作浏览器的部分功能&#xff0c;可以通过操作BOM对象的相关属性或者函数来完成。例如&#xff1a…

【docker:容器提交成镜像】

容器创建部分请看&#xff1a;点击此处查看我的另一篇文章 容器提交为镜像 docker commit -a "sinwa lee" -m "首页变化" mynginx lxhnginx:1.0docker run -d -p 88:80 --name lxhnginx lxhnginx:1.0为啥没有变啊&#xff0c;首页&#xff1f; 镜像打包 …

【CCF-C解刊】4区逆袭到1区TOP,这本期刊实力强劲,34天录用,7天见刊!

计算机类 • 好刊解读 今天小编带来Elsevier旗下计算机领域好刊的解读&#xff0c;这本期刊从4区逆袭成为中科院1区&#xff08;TOP&#xff09;&#xff0c;如此实力强劲的期刊&#xff0c;究竟如何&#xff1f; 如有相关领域作者有意向投稿&#xff0c;可作为重点关注&…

离散Hopfield神经网络分类——高校科研能力评价

大家好&#xff0c;我是带我去滑雪&#xff01; 高校科研能力评价的重要性在于它对高等教育和科研体系的有效运作、发展和提高质量具有深远的影响。良好的科研能力评价可以帮助高校识别其在不同领域的强项和薄弱点&#xff0c;从而制定战略&#xff0c;改进教学和科研&#xff…

Linux 多线程控制详解

目录 多线程编临界资源访问 互斥锁 API 简述 初始化互斥量 互斥量加锁/解锁 互斥量加锁(非阻塞方式) 互斥量销毁 程序示例 多线程编执行顺序控制 信号量 API 简述 初始化信号量 信号量 P/V 操作 信号量申请(非阻塞方式) 信号量销毁 程序示例 条件变量 创建和销毁…

node插件MongoDB(四)—— 库mongoose 的条件控制(三)

文章目录 前言一、运算符二、逻辑运算1. $or 逻辑或2. $and 逻辑与 三、正则匹配 前言 在mongodb 不能使用 > < > < ! 等运算符&#xff0c;需要使用替代符号。 一、运算符 > 使用 $gt< 使用 $lt> 使用 $gte< 使用 $lte! 使用 $ne 例子&#xff1a;获…

单片机启动流程

存储器 ​ 一个单片机中存在rom和ram&#xff0c;Soc也有rom和ram&#xff08;ddrx&#xff09;&#xff0c;部分Soc还包含MMU&#xff08;Memory Manage Unit 内存管理单元&#xff09;— &#xff08;用于系统内存管理&#xff0c;比如说虚拟内存空间&#xff0c;内存区间的…

Flink SQL自定义标量函数(Scalar Function)

使用场景&#xff1a; 标量函数即 UDF&#xff0c;⽤于进⼀条数据出⼀条数据的场景。 开发流程&#xff1a; 实现 org.apache.flink.table.functions.ScalarFunction 接⼝实现⼀个或者多个⾃定义的 eval 函数&#xff0c;名称必须叫做 eval&#xff0c;eval ⽅法签名必须是 p…

jenkins通知

构建失败邮件通知 配置自己的邮箱 配置邮件服务&#xff0c;密码是授权码 添加构建后操作 扩展 配置流水线 添加扩展 钉钉通知 Jenkins安装钉钉插件 钉钉添加机器人 加签 https://oapi.dingtalk.com/robot/send?access_token98437f84ffb6cd64fa2d7698ef44191d49a11…

为什么审计平台不适合进行数据库变更管理?

关于视源电子 广州视源电子科技股份有限公司 (CVTE) 成立于 2005 年 12 月&#xff0c;旗下拥有多家业务子公司。 截至 2022 年底&#xff0c;公司总人数超 6000 人&#xff0c;约 60% 为技术人员。公司的主营业务为液晶显示主控板卡和交互智能平板等显控产品的设计、研发与销…

C语言之文件操作(剩余部分)

上篇博客字数到极限了&#xff0c;给大家把内容补充在这一篇&#xff0c;我们还剩下文件读取结束的判定和文件缓冲区的内容没有介绍&#xff0c;让我们开始下面的学习吧&#xff01; 目录 1.文件读取结束的判定 1.1feof函数 1.2ferror函数 代码示例 2.文件缓冲区 2.1fflu…

Redis之主从复制

文章目录 一、什么是Redis主从复制&#xff1f;1.作用2.配置主从复制的原因3.环境配置 二、一主二从三、复制原理四、链路总结 一、什么是Redis主从复制&#xff1f; 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(ma…

用Go实现网络流量解析和行为检测引擎

1.前言 最近有个在学校读书的迷弟问我:大德德, 有没有这么一款软件, 能够批量读取多个抓包文件,并把我想要的数据呈现出来, 比如:源IP、目的IP、源mac地址、目的mac地址等等。我说&#xff1a;“这样的软件你要认真找真能找出不少开源软件, 但毕竟没有你自己的灵魂在里面,要不…

类与对象(2)

✨前言✨ &#x1f4d8; 博客主页&#xff1a;to Keep博客主页 &#x1f646;欢迎关注&#xff0c;&#x1f44d;点赞&#xff0c;&#x1f4dd;留言评论 ⏳首发时间&#xff1a;2023年11月11日 &#x1f4e8; 博主码云地址&#xff1a;博主码云地址 &#x1f4d5;参考书籍&…

C++动态库

C动态库 动态库文件&#xff08;Dynamic Link Library&#xff0c;DLL&#xff09;是程序在运行时所需要调用的库。静态库文件是程序在编译时所需要调用的库。 1 环境介绍 VS版本&#xff1a;VS2017 编程语言&#xff1a;C 2 功能介绍 使用VS2017项目模板创建C动态库生成…

Java 之 IO/NIO/OKIO

BIO blocking io AIO Asynchronous IO 从内存读取到写入--输出 从外部到内存 -- 输入 OutputStream //文件不存在则自动创建 try {OutputStream outputStream new FileOutputStream("text.txt");outputStream.write(a);outputStream.write(b);} catch (IOExcep…

Java-多态

1. 多态 1.1 多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 1.2 多态实现条件 在java中要实现多态&#xff0c;必须要满足如下几个条件&#xff0c;缺一不…