逆向工程
嵌云阁主
参与从系统设计到硬件调试和软件编码每一过程的工作
展开
-
逆向工程学习笔记(19):64位数据处理
在32位系统中使用64位的数据类型时,需要使用2个寄存器来保存数值的高32位和低32位,如double,uint64_t等,看下面的代码:; double __stdcall yfcstd::NormalizeAngle(double)0x300011E0 mov eax, dword [0x30003044]0x300011E5 mov ecx, dword [0x30003040]0x300011EB mov edx, dword [0x3000304c]0x300...原创 2021-05-03 00:08:46 · 389 阅读 · 0 评论 -
逆向工程学习笔记(18):浮点数比较
X86提供了一个叫FCOM的指令用以进行浮点数的比较:0x30001084 fcomp qword [0x30003068]上面的指令将ST(0)寄存器的值与一个全局变量进行比较,并设置浮点标志寄存器:这里的C3,C2,C0是FPU状态寄存器的3个比特位:紧接着使用一条FSTSW指令将FPU状态寄存器赋给AX最后就可以用test命令进行比较和跳转了。一个完整的指令序列:0x30001080 fld qword [esp + 4]0x30001084...原创 2021-04-27 00:00:29 · 440 阅读 · 0 评论 -
逆向工程学习笔记(17):回调函数
在C++中经常使用回调函数,下面看一段代码:0x30001009 mov ecx, dword [esp + 0xc]0x3000100D mov edx, dword [esp + 8]0x30001011 push ecx0x30001012 mov ecx, dword [esp + 8]0x30001016 push edx0x30001017 push ecx0x30001018 call eax从前面的代码已经知道,...原创 2021-04-18 23:02:48 · 463 阅读 · 0 评论 -
逆向工程学习笔记(16):test条件跳转
X86下经常使用test+je指令来完成跳转。0x30001005 test eax, eax0x30001007 je 0x3000101atest 指令用于两个操作数的按位AND运算,并根据结果设置标志寄存器,结果本身不会写回到目的操作数。上面两行的用法是用来测试寄存器是否为0: 寄存器为0, 则ZF零标志为1, 则跳转因此对于上面的代码块,很容易得到对应的C++代码:If块中的代码没有完全解析出来,留待明天吧。...原创 2021-04-16 00:07:38 · 468 阅读 · 1 评论 -
逆向工程学习笔记(15):__stdcall简单验证
在vs2017下简单验证__stdcall调用时的出入栈方式,win32平台,Release,关闭帧变量的生成。 void __stdcall test() 测试函数: void __stdcall test() { return; }汇编代码:调用者: int __stdcall test() 测试函数: int __stdcall test() { return 1;...原创 2021-04-15 00:00:24 · 345 阅读 · 0 评论 -
逆向工程学习笔记(14):验证
在VS2017下编译此函数,查看汇编:可以看到,在默认的编译参数下,VS2017引入了ebp并入栈,因此输入参数的偏移量由4变成了8。关闭VS2017编译器中创建帧指针的功能:这里/Oy参数默认是不启用的,在此将之改为是。再次编译并查看汇编:比较原汇编:; void __stdcall SetInternalErrorHandler(fnCallback113)0x30001020 mov eax, dword [esp + 4]0x30001024 ...原创 2021-04-14 00:25:26 · 216 阅读 · 0 评论 -
逆向工程学习笔记(13):回调函数的初始化
在函数中,使用了g_pInternalErrorHandler这一个全局变量,且地址为0x30004150。查询文件中的段定义:可知这个变量位于.rdata段,且这个段的文件偏移量为12288,根据文件偏移量读取全局变量的初始化值:再转换为C++的初始化语句:/* 0x30004150 */ extern fnCallback113 g_pInternalErrorHandler;/* 0x30004150 */fnCallback113 g_pInternalE..原创 2021-04-13 00:00:56 · 317 阅读 · 0 评论 -
逆向工程学习笔记(12):代码整理
通过前面的分析,我们可以得到此函数的逆向代码:void __stdcall SetInternalErrorHandler(fnCallback113 param1){ uint32_t esp_0 = 0; fnCallback113 eax_0 = 0; struct CStack_0x3000102...原创 2021-04-12 23:48:11 · 209 阅读 · 0 评论 -
逆向工程学习笔记(11):类型推断
类型推断即通过代码的组织形式,已知类型等可用信息对变量的类型进行推断。如在DegToRad函数中,使用fld指令0x40002040 fld qword [0x40003038]我们即可推断[0x40003038]这个全局变量的类型为double类型。在当前函数中,由于[esp + 4]这个局部变量来自于第一个参数,而第一个参数的类型为fnCallback113,因此可以推断[ESP + 4]这个局部变量的类型也为fnCallback113。但是在更多的代码中,并不存在这样一...原创 2021-04-11 23:41:05 · 198 阅读 · 0 评论 -
逆向工程学习笔记(10):栈的再思考
在DegToRad函数中,简单创建了一个Local_0x0004的局部变量来表示[esp + 4]。这种方式无法处理局部变量中使用结构体或者类的情况。换个角度看,数据在栈中的表示完成可以用一个结构体进行表示,这样可以避免编译器对局部变量进行重排,而不是从上到下的按顺序排列,同时还可以与后继结构体的分析共用代码。说做就做,对这部分代码进行一些修改,在逆向代码里栈变量就变成了: struct CStack_0x30001020...原创 2021-04-11 23:06:19 · 281 阅读 · 0 评论 -
逆向工程学习笔记(9):SetInternalErrorHandler
这个也是一个比较简单的函数:; void __stdcall SetInternalErrorHandler(fnCallback113)0x30001020 mov eax, dword [esp + 4]0x30001024 mov dword [0x30004150], eax0x30001029 ret 4原函数功能也就是设置一个错误处理的回调函数,具体实现就是将这个回调函数指针保存到一个全局变量中。与DegToRad相比,除了MOV指令外,这个函数其实并没...原创 2021-04-11 22:34:53 · 166 阅读 · 0 评论 -
逆向工程学习笔记(8):验证
将逆向得到的代码整理成可读性较好的代码:double __stdcall DegToRad(double param1){ /* 0x40002050 */ return D_PI * param1 * 0.00555555555555556;}在vs2017下进行编译,查看其生成的汇编:在Debug状态下:可以看到差异还是比较大的,这是因为在debug状态下没有使用FPU,且在前后插入了栈检查的代码。在release状态下:可以看到在vs2017下,D_P...原创 2021-03-31 00:23:38 · 213 阅读 · 0 评论 -
逆向工程学习笔记(7):ret 8
最后一条指令:0x40002050 ret 8因为是__stdcall,所以在返回指令中带上了栈的大小,8个字节。由于是返回double类型,因此我们直接将ST0中的结果返回: /* 0x40002050 */ return st0_2;最终逆向分析得到的C++代码:double __stdcall DegToRad(double param1){ double st0_0 = 0; uint32_t esp_0 = 0;...原创 2021-03-30 23:21:49 · 2234 阅读 · 0 评论 -
逆向工程学习笔记(6):fmul qword [0x40003050]
看下一条fmul指令:0x4000204A fmul qword [0x40003050]这条fmul指令的功能是将ST0寄存器里的数和一个指定地址里的数相乘,再将结果放入ST0寄存器。这里的ST0寄存器里的初值来自于上一条FMUL指令,因此沿用上一条指令创建的变量st0_1。再创建一个变量st0_2保存结果。这里引用到了地址[0x40003050],这个地址没有查找到对应的全局变量,因此这里的数可能是一个cpp文件中用static定义出来的全局变量,因为其作用域只在此cpp文件中...原创 2021-03-29 23:57:26 · 363 阅读 · 0 评论 -
逆向工程学习笔记(5):fmul qword [esp + 4]
接下来看fmul指令:0x40002046 fmul qword [esp + 4]功能很简单,将ST0寄存器里的数和栈中的数相乘,再将结果放入ST0寄存器。这里的ST0寄存器的值来自于上一条FLD指令,因此我们沿用上一条指令创建的st0_0寄存器表示原有的值,再新建一个变量st0_1来保存结果。再创建一个Local_0x0004的局部变量来表示[esp + 4]。因此这条汇编语句转换成C++就可以表示为: /* 0x40002046 */ st0_1 = st0_...原创 2021-03-29 23:29:35 · 491 阅读 · 0 评论 -
逆向工程学习笔记(4):fld指令
fld指令相对简单,就是将一个源操作数放到ST0寄存器里。对应到C++代码中,我们简单用一个局部变量st0_0来表示目标寄存器。对于源操作数,radare的反汇编指令直接查找到了一个全局变量[sym.D_PI],但对于逆向工程来说,我们的目标是得到C/C++代码,这点信息显然是不够的。我们看伪汇编代码:0x40002040 fld qword [0x40003038][0x40003038]这个地址是数据段的内容,可以直接从文件中读取内容。这8个字节直接转换为double类...原创 2021-03-29 00:10:14 · 1113 阅读 · 0 评论 -
逆向工程学习笔记(3):FPU基本操作
X87内部执行时可以使用8个80bit的数据寄存器及控制寄存器、状态寄存器等:对于这8个数据寄存器,X87是以栈的形式使用的:在其状态寄存器中使用了3个比特位以记录栈顶的位置。有入栈或者出栈时此指针进行移动,当超过8个数时进行循环覆盖。在intel的数据手册中很贴心的给出了一个计算的例子:第一条FLD指令将5.6这个立即数放入ST(0),图(a) FMUL指令将ST(0)中的数和2.4相乘得到结果13.44,并放入ST(0)中,图(b)。 同样的操作,指令3和指令4计算3.8原创 2021-02-26 23:35:29 · 443 阅读 · 0 评论 -
逆向工程学习笔记(2):出发--DegToRad
分析之路先从一个最简单的角度转弧度函数开始:; double __stdcall DegToRad(double)0x40002040 fld qword [sym.D_PI]0x40002046 fmul qword [esp + 4]0x4000204A fmul qword [0x40003050]0x40002050 ret 8很简单的一个函数。先百度下FPU:浮点运算器(英文:floating point unit,简称FPU)是计算机...原创 2021-02-26 22:24:03 · 324 阅读 · 0 评论 -
逆向工程学习笔记(1):前言
很长时间没更新了,回顾下没更新的这段时间,似乎掌握的技术也没有更新,太可怕了。失业了肿么办?据说人才市场对中年大叔极度不友好!!吓得我赶紧放下手机,打开电脑,干啥好呢????据说AI很热门,虽然学了半吊子图像处理,好难啊,想想还是算了……按说嵌入式开发不错,也算老本行了,其实从本质上看也十几年未变,似乎没啥挑战性。。。。。。再说了难道下班了还要处于工作状态?FPGA、硬件开发?就现在这环境,尤其是个人,似乎也没什么搞头。。。。。。……逆向工程吧?就它了!!!说不定站在前人原创 2021-02-26 21:43:05 · 397 阅读 · 0 评论