IDAPython详细版(二)

六:操作数

可以使用idc.get_openrand_typed(ea,n)得到操作数的类型。ea是地址,n是索引

这里有8种不同类型的操作数类

0_void 如果一个指令木有任何操作数它将返回0

0_reg 如果一个操作数是一个普通的寄存器将返回此类型。这个值在内部表示为1.

o_mem 如果一个操作数是直接内存引用,它将返回这个类型,这个值在内部表示为2.这种类型是有用的在date段查找引用。

o_phrase 这个操作数被返回则这个操作数包含一个基本的寄存器或者一个索引寄存器,这个值在内部表示为3.

o_displ这个操作数被返回则 操作数包含寄存器和一个位移值 这个位移值是一个整数,例如ox18。这是常见的当一条指令访问在一个结构体中。在内部,它表示为4的值。

o_for 这个操作数不是很常见当逆向x86或者x86_64 时 它是用来寻找操作数的访问立即数远地址的,它在内部表示为6。

o_near 不是很常见,寻找近地址 内部表示为7。

举个粒子:

当逆向可执行文件的内存dump时,操作数不能被识别为偏移

seg000:00BC1388 push 0Chseg000:00BC138A push 0BC10B8hseg000:00BC138F push [esp+10h+arg_0]seg000:00BC1393 call ds:_strnicmp

push 0bc10b8h是一个内存偏移量。如果我们将其改为数据类型,我们会看到字符串偏移量。如果要自动化,如下:

idc.get_inf_attr(INF_MIN_EA) 获得调用最小地址

idc.get_inf_attr(INF_MAX_EA)  获得调用最大地址

idc.op_plain_offset(ea, n, base)  将操作数转化为偏移量  第一个参数是地址,第二个参数n是操作数索引,第三个参数base是基地址

min = idc.get_inf_attr(INF_MIN_EA)max = idc.get_inf_attr(INF_MAX_EA)# for 每个已知函数for func in idautils.Functions():flags = idc.get_func_attr(func, FUNCATTR_FLAGS)# 跳过 library 和 thunk 函数if flags & FUNC_LIB or flags & FUNC_THUNK:continuedism_addr = list(idautils.FuncItems(func))for curr_addr in dism_addr:if idc.get_operand_type(curr_addr, 0) == 5 and (min < idc.get_operand_value(curr_addr, 0) < max):idc.OpOff(curr_addr, 0, 0)if idc.get_operand_type(curr_addr, 1) == 5 and (min < idc.get_operand_value(curr_addr, 1) < max):idc.op_plain_offset(curr_addr, 1, 0)

七:基本块

基本块是木有分支的直线代码序列,有一个单入口点和一个单出口点组成。

在分析程序的控制流时,基本块非常用。在使用函数的图分解视图时,通常可以观察到rda对基本块的表示。使用基本块进行分析的一些值得注意的粒子是 用于识别循环或者控制流混淆哦。当一个基本块将控制权转移到另一个块时,下一个块称为后继承块,前一个块称为predecessors。

.text:00401034 push esi.text:00401035 push edi.text:00401036 push 0Ah ; Size.text:00401038 call ds:malloc.text:0040103E mov esi, eax.text:00401040 mov edi, offset str_encrypted.text:00401045 xor eax, eax ; eax = 0.text:00401047 sub edi, esi.text:00401049 pop ecx.text:0040104A.text:0040104A loop: ; CODE XREF: _main+28↓j.text:0040104A lea edx, [eax+esi].text:0040104D mov cl, [edi+edx].text:00401050 xor cl, ds:b_key ; cl = 0.text:00401056 inc eax.text:00401057 mov [edx], cl.text:00401059 cmp eax, 9 ; index.text:0040105C jb short loop.text:0040105E push esi.text:0040105F push offset str_format.text:00401064 mov byte ptr [esi+9], 0.text:00401068 call w_vfprintf.text:0040106D push esi ; Memory.text:0040106E call ds:free.text:00401074 add esp, 0Ch.text:00401077 xor eax, eax ; eax = 0.text:00401079 pop edi.text:0040107A pop esi.text:0040107B retn.text:0040107B _main endp

以上函数分为三个块,异或从0x40104a开始。0x401050是异或的关键点。

ea = 0x0401050
f = idaapi.get_func(ea)
fc = idaapi.FlowChart(f, flags=idaapi.FC_PREDS)
for block in fc:             #这个函数的所有块print("ID: %i Start: 0x%x End: 0x%x" % (block.id, block.start_ea,block.end_ea))if block.start_ea <= ea < block.end_ea:print(" Basic Block selected")successor = block.succs()  #包含后续地址的生成器for addr in successor:print(" Successor: 0x%x" % addr.start_ea)pre = block.preds()  #包含前身地址的生成器for addr in pre:print(" Predecessor: 0x%x" % addr.end_ea)if ida_gdl.is_ret_block(block.type):  #返回块print(" Return Block")
>>> Successor: 0x40104a
>>> ID: 1 Start: 0x40104a End: 0x40105e
>>> Basic Block selected
>>> Successor: 0x40105e
>>> Successor: 0x40104a
>>> Predecessor: 0x40104a
>>> Predecessor: 0x40105e
>>> ID: 2 Start: 0x40105e End: 0x40107c
>>> Predecessor: 0x40105e
>>> Return Block

每个块包含以下属性:

id:函数中每块都有一个唯一索引,从0开始

type:有以下类型

    • fcb_normal:表示普通块,内部为0
    • fcb_indjump:是否以间接跳转结束,内部为1
    • fcb_ret:返回块,内部为2
    • fcb_cndret:是否为条件返回,内部为3
    • fcb_noret:无返回块,内部为4
    • fcb_enoret:不属于函数且没有返回的块,内部为5
    • fcb_extern:外部普通块,内部为6
    • fcb_error:通过函数结束来传递执行的块,内部为7
  • start_ea:基本块开始地址
  • end_ea:基本快结束地址
  • preds:一个函数,它返回一个包含所有前身地址的生成器
  • succs:一个函数,它返回包含所有后续地址的生成器。

     

八:结构

在编译过程中,结构布局,结构名称和结构类型将会被删除。

重构结构和正确标记结构成员可以极大帮助逆向过程。

下面是x86 shellcode中常见的代码片段。

完整代码遍历器结构包含 线程环境块(TEB) 和 进程环境快(PEB) 来找到kernell32.dll的基地址。

seg000:00000000 xor ecx, ecxseg000:00000002 mov eax, fs:[ecx+30h]seg000:00000006 mov eax, [eax+0Ch]seg000:00000009 mov eax, [eax+14h]

shellcode的下一步是遍历PE文件,查找window api。

由于要解析所有不同结构,除非对结构偏移量进行标记,否则很容易丢失。

使用下列代码标注对应结构名称:

idc.add_default_til 加载 类型库(TIL), TIL是IDA自己的c/c++格式头文件。它包含结构、枚举、联合和其他数据类型的定义。在IDA中可以通过shift+F11打开。idc.add_default_til会返回加载状态。

在TIL加载后,使用import_type将TIL各个定义导入带IDB中。

idc.import_type(idx, type_name),第一个参数是type的索引,每一个类型都有一个所以和id。-1代表这类型应该将该类型添加到IDA导入类型的末尾。

idc.get_struc_id 获得结构id

idc.op_stroff(ea, n, strid, delta)   偏移地址处增加名字。

第一个参数是包含将要被标记的偏移量的指令的地址(ea)。第二个参数是操作数,在下面的例子中,因为我们想要更改mov eax, fs:[ecx+30h]中的0x30标签,我们需要为第二个参数传递一个值1。第三个参数是类型id,第四个参数通常是0.

status = idc.add_default_til("ntapi")if status:idc.import_type(-1, "_TEB")idc.import_type(-1, "PEB")idc.import_type(-1, "PEB_LDR_DATA")ea = 2teb_id = idc.get_struc_id("_TEB")idc.op_stroff(ea, 1, teb_id, 0)ea = idc.next_head(ea)  #获得下一个指令地址peb_ldr_id = idc.get_struc_id("PEB_LDR_DATA")idc.op_stroff(ea, 1, peb_ldr_id, 0)ea = idc.next_head(ea)idc.op_stroff(ea, 1, peb_ldr_id, 0)

idc.del_struc(id) 删除结构

idc.add_struc(index, name, is_union)  增加结构  第一个参数是索引,-1添加到后面,第二个参数是结构名字,第三个参数是定义的新结构是否为union,0代表不是union。

后面的待更新:(没学会自己。。。)

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

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

相关文章

数据分析求职-岗位介绍

这是咱们干货开始的第一篇文章&#xff0c;后续我尽量会保持日更的节奏和大家做分享~ 在未来所有分享的内容展开之前&#xff0c;咱们有必要先彻底、深入地了解下数据分析这个岗位。如果你还在犹豫是否要走数据分析的路&#xff0c;或者你已经拿了数据分析的offer想了解下将来…

nuScenes数据集解压

下载Full dataset&#xff08;v1.0&#xff09;的Trainval和Test部分&#xff0c;放到data/nuscenes文件夹下 如果下载了Map expansion&#xff0c;则需要现在nuscenes下新建一个文件夹maps&#xff0c;把nuScenes-map-expansion-v1.3.zip解压到里面&#xff0c;可以使用unzip…

vue+springboot项目上传部署tomcat

下载及安装Tomcat 进入tomcat官网&#xff0c;Tomcat官网 选择需要下载的版本&#xff0c;点击下载下载路径一定要记住&#xff0c;并且路径中尽量不要有中文 下载后是压缩包 .zip&#xff0c;解压后 tomcat系统各个文件夹目录是什么意义&#xff1a; bin&#xff1a;放置的是…

【Java集合篇】接上篇博文--为什么在JDK8中HashMap要转成红黑树

为什么在JDK8中HashMap要转成红黑树 ✔️为什么不继续使用链表✔️为什么是红黑树✔️红黑树的性能优势 ✔️ 拓展知识仓✔️为什么是链表长度达到8的时候转✔️为什么不在冲突的时候立刻转✔️关于为什么长度为8的时候转(源码注释解读)✔️为什么长度为6的时候转回来?✔️双向…

Python+django+selenium搭建简易自动化测试

该平台会集成UI自动化及api自动化&#xff0c;里面也会涉及到一些简单的HTML等前端&#xff0c;当然都是很基础的东西。在以后的博客里&#xff0c;我会一点点的尽量写详细&#xff0c;帮助一些测试小白一起成长&#xff0c;当然我也是个小菜鸡。 第一章 django 搭建平台。 1…

大创项目推荐 深度学习图像修复算法 - opencv python 机器视觉

文章目录 0 前言2 什么是图像内容填充修复3 原理分析3.1 第一步&#xff1a;将图像理解为一个概率分布的样本3.2 补全图像 3.3 快速生成假图像3.4 生成对抗网络(Generative Adversarial Net, GAN) 的架构3.5 使用G(z)生成伪图像 4 在Tensorflow上构建DCGANs最后 0 前言 &#…

如何在CentOS7部署宝塔面板并通过内网穿透实现远程登录面板

文章目录 一、使用官网一键安装命令安装宝塔二、简单配置宝塔&#xff0c;内网穿透三、使用固定公网地址访问宝塔 宝塔面板作为建站运维工具&#xff0c;适合新手&#xff0c;简单好用。当我们在家里/公司搭建了宝塔&#xff0c;没有公网IP&#xff0c;但是想要在外也可以访问内…

【Java基础篇】 try中return A,catch中return Bfinally中return C,最终返回值是什么?

try中return A&#xff0c;catch中return Bfinally中return C&#xff0c;最终返回值是什么? ✔️典型解析✔️拓展知识仓✔️finally 和 return 的关系 ✔️ final、finally、finalize有什么区别✔️final✔️finally✔️ finalize ✔️典型解析 最终的返回值将会是C 因为 fi…

CTFHub | 存储型

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习&#xff0c;实训平台。提供优质的赛事及学习服务&#xff0c;拥有完善的题目环境及配套 writeup &#xff0c;降低 CTF 学习入门门槛&#xff0c;快速帮助选手成长&#xff0c;跟随主流比赛潮流。 0x01 题目描述…

Vue3-36-路由-路由的元数据信息 meta

什么是 meta 简单的理解&#xff0c;meta 就是路由对象 的一个属性对象&#xff0c; 可以 通过这个 属性给 路由对象添加 一些必要的属性值&#xff0c; 在使用路由对象时可以获取到这个属性型对象&#xff0c;从而进行一些其他的逻辑判断。 meta 这个非常的简单&#xff0c;就…

如何使用Docker本地部署一个开源网址导航页并分享好友公网使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

linux 浅练一下哈

1.新建用户test不建家目录不允许登录&#xff0c;uid为10086_____________________ useradd -u 10086 -M -s /sbin/nologin 2.将 /opt 文件夹中所有文件的属主&#xff0c;属组改成&#xff0c;test_______________________ chown -R test.test /opt chown -R …