ida使用技巧之动态调试
ida使用技巧之动态调试
来源 https://blog.csdn.net/m0_52164435/article/details/124871122
一、ida动态调试
1、介绍
众所周知,ida是一款非常优秀的反编译软件,在静态逆向中是属于屠龙宝刀一般的存在,他不仅仅有着优秀的静态分析能力,同时还有着极其优秀的动态调试能力,甚至可以直接对生成的伪代码进行调试,这一点远超其他只能在汇编层进行调试的动态调试器,极大的增加了动态调试程序的可读性,能够节省很多精力。甚至可以以远程调试的方式,将程序部署在linux或安卓端上,实现elf文件和so文件等的动态调试。
2、本地调试(Windows)
首先从本地动态调试开始
加载目标文件
万年第一步,使用ida打开目标文件,然后点击菜单项中的“Debugger”
选择select debugger
本地调试Windows文件,所以这里选择local Windows debugger。
点击ok之后,再看debugger菜单发现此时菜单以新的形式展开
此时再点击带有绿色三角符号的“Start process”即可开始调试程序
ida还支持另一种调试方式,即将目标文件附加到一个正在运行的进程上,以调试某些无法独立运行的文件,如果想以这种方式进行调试,则在选好调试器后点击“Attach to process”后即可选择附加进程
调试器界面
经过一段时间的加载之后,进入了调试器界面
“IDA-view-eip”界面是反汇编窗口,在这里点击f5,可以进入伪代码调试
可以说是非常的好用
下面的“hex view”顾名思义,右边从上到下分别是级寄存器/标志寄存,加载到进程内存空间中的可执行文件和共享库,双击模块名称可打开该模块输出的符号表,再向下看就是栈窗口
调试命令
ida快捷键 | 功能 |
---|---|
F7 | 单步步进 |
F8 | 单步步过 |
F9 | 继续运行程序 |
F4 | 运行到光标所在行 |
Ctrl + F7 | 直到该函数返回时才停止 |
Ctrl + F2 | 终止一个正在运行的进程 |
F2 | 设置断点 |
断点
ida的动态调试同样支持设置条件断点
设置好断点后,右键断点,点击第二行“Edit breakpoint”即可打开断点设置菜单
location栏是断点地址,condition栏则是条件断点的表达式
例:EAX == 12
指当EAX的值为12时中断,同时,因为condition栏由IDC表达式支持,所以可以使用一些IDC的函数。
比如:GetRegValue(“ZF”)
指当ZF的值不为0时中断
监视窗口
ida同样也支持对数据的监视,需要监视的数据一般在栈或者数据块中,进入栈或者数据,点击右键打开菜单,选择“Add watch”
即可在窗口“watch list”中显示,如果需要删除,则按“Delete”键
3、远程调试
ida支持远程调试Windows、linux、Android、Mac OS的二进制文件,将文件放在远程的对应系统服务器上,ida远程连接服务器,在服务器上运行、调试程序,并在本地客户端显示调试界面。界面视图上和本地调试并没有区别。
如果需要远程调试,首先需要将ida的服务端部署在远程服务器上,ida的服务端存储在ida目录中的dbgsrv文件中
将需要调试的文件和服务端版本放入服务器中,然后运行服务端,会默认在23946端口启动ida服务端程序,以linux为例
被调试程序是64位elf文件,所以在linux端运行linux_server64,然后回到客户端
客户端的第一步没什么变化,在菜单选择debugger栏,在选择debugger时,选择Remote Linux debugger
然后在菜单中先选择“Process option”进行设置
打开后页面如下
第一行application和input file选择被调试文件在服务端中的存储路径。下面第三行的directory是存储路径,直接选被调试文件所在目录就行。再下面第四行的是程序启动时传入的参数,可以为空。第五行则“Hostname”则填服务端的ip和端口号,我这里选的服务端是虚拟机。最后一行的password是linux_server启动时设置的密码,如果没有设置,则为空即可。全部设置正确之后就可以开始调试了
点击“start process”开始调试程序
可以看到在服务端程序已经成功启动
接下来的步骤和本地调试并没有什么区别不再赘述。其他安卓和Mac的文件远程调试也是大同小异,也不再多说了。
ida使用技巧:ida python
来源 https://blog.csdn.net/m0_52164435/article/details/124878537
一、简介
ida python是ida中一个很强大的功能,早期需要另行下载,后来在6.8版本成为了内置插件,而在7.5版本更新后又对函数的命名进行了规范修整。
ida python官方提供了函数文档:https://www.hex-rays.com/wp-content/static/products/ida/support/idapython_docs/
IDC api函数文档:https://www.hex-rays.com/products/ida/support/idadoc/162.shtml
二、使用
现在几乎没有人在使用ida 6.8及以下版本了,所以ida python的安装不再介绍,直接从使用说起。
小问题
首先先解决一个小问题,因为ida7.5更新后函数名称不同,再使用老版本脚本或函数时,会出现NameError: name ‘XXXX’ is not defined这样的报错提示,解决办法有两种
方法一:
在代码面前:
from idc_bc695 import *
方法二:
修改配置文件
进入ida的存储目录,找到cfg文件下的idapython.cfg文件,修改其中参数“AUTOIMPORT_COMPAT_IDA695”值为YES
当然,官方更新这些api函数的名称肯定是有道理的,所以建议遇到有问题的函数之后去官方提供的对照表中查看一下新版本的函数名,链接如下:
https://www.hex-rays.com/products/ida/support/ida74_idapython_no_bc695_porting_guide.shtml
使用方法
使用ida python有三种方法
第一种:
在菜单栏中点击“文件”->“脚本命令”即可打开脚本编写窗口,快捷键是Shift+F2
可以看到,在下方的设置选项中有一个Scripting language,在这里可以选择python或者IDC。如果选IDC的话,就只能使用IDC函数了。
第二种:
直接引用编写好的脚本文件,在菜单栏中点击“文件”->“引用脚本”即可,快捷键是Alt+F7
第三种:
直接在下方命令行输入
常用函数
获取地址
-
idc.get_screen_ea() 旧版:ScreenEA()
获取 IDA 调试窗口中此时光标指向代码的地址。 -
idc.here()
获取当前指令位置 -
ida_ida.inf_get_min_ea()
获取最小地址 -
ida_ida.inf_get_start_ip()
-
ida_ida.inf_get_max_ea() 旧版:idc.MaxEA()
获取最大地址 -
idc.read_selection_start() 旧版:idc.SelStart()
当前选择区块的起始地址 -
idc.read_selection_end() 旧版:idc.SelEnd()
当前选择区块的结束地址
获取段
- idc.get_first_seg() 旧版:FirstSeg()
访问程序中的第一个段。 - idc.get_next_seg() 旧版:NextSeg()
访问下一个段,如果没有就返回 BADADDR。 - idc.selector_by_name(string SegmentName) 旧版:SegByName( string SegmentName )
通过段名字返回段基址 - idc.get_segm_end(long Address) 旧版:SegEnd( long Address )
获取传入地址的段尾地址 - idc.get_segm_start( long Address )旧版:SegStart( long Address )
获取传入地址的段首地址 - idc.get_segm_name( long Address ) 旧版:SegName( long Address )
获取传入地址的段名 - Segments()
获取所有段名
获取数值
- idc.get_wide_byte(addr) 旧版:Byte(addr)
以字节为单位获取地址处的值 - idc.get_wide_word(addr) 旧版:Word(addr)
以2字节(字)为单位获取地址处的值 - idc.get_wide_dword(addr) 旧版:Dword(addr)
以4字节为单位获取地址处的值 - idc.get_qword(addr) 旧版:Qword(addr)
以8字节为单位获取地址处的值
处理数值
- ida_bytes.patch_byte(addr,value) 旧版:idc.PatchByte(addr,value)
修改addr地址的值为value.每次修改一个字节 - ida_bytes.patch_word(addr,value) 旧版:idc.PatchWord(addr,value)
修改addr地址的值为value.每次修改两个字节 - ida_bytes.patch_Dword(addr,value) 旧版:idc.PatchDword(addr,value)
修改addr地址的值为value.每次修改四个字节 - ida_bytes.patch_Qword(addr,value) 旧版:idc.PatchQword(addr,value)
修改addr地址的值为value.每次修改八个字节
函数处理相关
-
Functions( long StartAddress, long EndAddress )
返回一个列表,包含了从 StartAddress 到 EndAddress 之间的所有函数。 -
Chunks( long FunctionAddress )
返回一个列表,包含了函数片段。每个列表项都是一个元组(chunk start, chunk end) -
idc.get_name_ea_simple( string FunctionName ) 旧版:LocByName( string FunctionName )
通过函数名返回函数的地址。 -
idc.get_func_off_str( long Address ) 旧版:GetFuncOffset( long Address )
通过任意一个地址,然后得到这个地址所属的函数名,以及给定地址和函数的相对位移。 然后把这些信息组成字符串以"名字+位移"的形式返回。 -
idc.get_func_name( long Address ) 旧版:GetFunctionName( long Address )
通过一个地址,返回这个地址所属的函数。 -
CodeRefsTo( long Address, bool Flow )
返回一个列表,告诉我们 Address 处代码被什么地方引用了,Flow 告诉 IDAPython 是否要 跟踪这些代码。 -
CodeRefsFrom( long Address, bool Flow )
返回一个列表,告诉我们 Address 地址上的代码引用何处的代码。 -
DataRefsTo( long Address )
返回一个列表,告诉我们 Address 处数据被什么地方引用了。常用于跟踪全局变量。 -
DataRefsFrom( long Address )
返回一个列表,告诉我们 Address 地址上的代码引用何处的数据。
=============== End