IDA逆向程序的经验总结
关于一些类型转换以及指针和地址的总结
最可以拿来当教训的应该是 hide cast 功能
如果隐藏了,就是这样的
如果SaveAShouldShowStreamIndex是char类型的数组,那会怎么样呢,一次取一个字节和取四个字节就完全不一样了.当然如果你再逆向的时候就已经知道了这个数组的类型那就没问题,但是也应该注意没到必要的时候不要Hide Casts ,虽然你的代码会被很多类型转换搞得头晕,但是关掉真的影响你的逆向准确性.
关于F5汇编代码不能转成c的伪代码的几个问题总结
1.jmpout的问题
jumpot
如果遇上jumpout的话,一般是只能动态调试去跟踪调试代码.很少能将jumpOut的汇编修改成能反出伪C的形式.
2.positive sp value has been found 的问题
出现这个问题一般都是能解决的
这个请参考这个帖子:
https://blog.csdn.net/u010334666/article/details/82937413
3.call analysis failed
这种一般是函数内部的参数没有解析正确,所以如果想正确解析,需要读取去修改函数内部调用函数的参数.
参考帖子:https://www.cnblogs.com/echo579/p/6564433.html
有时候 switch 也可能会导致 出现 jumpout 解决办法是 把jumpout签名的一截汇编 先U 撤销然后再重新反编译 就能正确反编译出来了
或者说函数的没有定位到正确的结尾 也会导致jumpout 这就需要正确定位到函数的末尾 才能将jumpout改成正确的代码
有时候 换一个版本的IDA 去看 也能看出一些问题 比如你用IDA7.0 有时候反编译出来的内容不正确 那就用IDA6.8 去分析 没准比IDA7.0 分析的要准确一点
对于浮点数的逆向思路
出现COERCE_FLOAT的宏一般是接收的返回值错了,或者是函数的返回值有问题,
还有出现这种LOWWORD的宏一般是参数的问题,有时可能是double的参数,IDA反成了两个Int的类型的参数,因为32位的ARM本身就没有64位的类型,需要自己修改函数的参数和返回值才能得到正确的值,还有一些其他的标志也可以看出是浮点数的运算:比如函数内部大量的位移运算,大量参数未赋值直接参与运算等
对于ARM汇编的一些思路和技巧
局部变量的地址 sp+xx标识
临时变量,在使用的时候用什么寄存器标识
暂时先想到这些,以后再补充
对单片机项目的逆向要点
需要掌握一定的单片机开发知识.
很多地方涉及到一些硬件的接口和屏幕显示的接口,都是以地址的形式表示,如:0x20004F64,0x20005014 ,0x64000400 ,0x4001300等的地址
看到这种地址上的赋值,就需要去参考手册了
IDA 反编译一些可变参数的技巧和总结
要IDA 能正确识别出可变参数的函数的参数 首先要清楚定位到可变参数前最后一个确定的参数 这样IDA才能识别出来
C语言中对可变参数的读写依赖于宏va_start、va_arg和va_end
这三个宏的定义如下:
-
void va_start(va_list ap,
last);//取第一个可变参数(如上述printf中的i)的指针给ap,last是函数声明中的最后一个固定参数(比如printf函数原型中的*fromat); -
type va_arg(va_list ap,
type);//返回当前ap指向的可变参数的值,然后ap指向下一个可变参数;type表示当前可变参数的类型(支持的类型位int和double); -
void va_end(va_list ap);//将ap置为NULL
还有一种方法不用去使用定义的都参数的宏也能去读取参数
这是我在IDA反汇编中看到的 既然IDA把他反汇编成这样 那也肯定可以 然后就写代码测试一下吧
为了测试可变参数 如何在IDA中被识别 写了一个测试程序 如下:
int function(int a,int b,int Num, ...)
{
int *p;
p = &Num;//通过一个指针指向可变参数的最后一个确定位置
int k = 0;
p++;//指针向后偏移就可以取到参数的值
for (int i = 0; i < Num; i++)
{
k += *p;
p++;
}
return k;
}
int main(int argc, char* argv[])
{
printf("hello");
return function(6, 2, 3, 4, 5, 6);
}
这应该是应该传递参数的时候是根据栈的循序来的 所以通过指针去指向栈的地址 然后+1 就取到了下一个参数的值
但是这样的话就对反汇编产生了一些困难
所以还是需要手动去解析下 让他变成那种 宏的模式
IDA 识别可变参数
然后我把函数改成了这种宏的形式让IDA去识别
#include "stdafx.h"
#include <stdarg.h>
int function(int a,int b,int Num, ...)
{
int k = 0;
va_list ap;
/*int *p;
p = &Num;
p++;*/
va_start(ap,Num);
for (int i = 0; i < Num; i++)
{
k += va_arg(ap,int);
}
va_end(ap);
return k;
}
int main(int argc, char* argv[])
{
printf("hello");
return function(6, 2, 3, 4, 5, 6);
}
IDA反汇编的function的代码如下:
int __cdecl sub_411710(int a1, int a2, int a3, char a4)
{
int v4; // ecx
int i; // [esp+D0h] [ebp-20h]
char *v7; // [esp+DCh] [ebp-14h]
int v8; // [esp+E8h] [ebp-8h]
v8 = 0;
sub_41135C(v4);
v7 = &a4;
for ( i = 0; i < a3; ++i )
{
v7 += 4;
v8 += *((_DWORD *)v7 - 1);
}
return v8;
}
可以看出来 既识别不对参数 也没认出这是可变参数
然后手动修改函数参数
修改两个地方:
1.找到可变参数前的最后一个确定的参数
2.在最后一个参数后加上三个 …
然后代码变成了如下形式:
int sub_411710(int a1, int a2, int a3, ...)
{
int i; // [esp+D0h] [ebp-20h]
va_list v5; // [esp+DCh] [ebp-14h]//变量的类型也识别出来了
int v6; // [esp+E8h] [ebp-8h]
va_list a4; // [esp+104h] [ebp+14h]
va_start(a4, a3);//识别出了宏
v6 = 0;
sub_41135C();
va_copy(v5, a4);
for ( i = 0; i < a3; ++i )
{
v5 += 4;//指向参数的指针
v6 += *((_DWORD *)v5 - 1);
}
return v6;
}
IDA Functions window 函数跟随 Pseudocode IDA-View窗口变化
右键点击functions窗口 Turn on synchronization
[autohidden] 问题
[autohidden] The current structure is just a copy of a local type.
If you edit it from the struct view, IDA will sync the changes
back to the local type and will consider the type as manually defined
by the user. We recommend you to edit the local type instead
of editing the structure. Do you want to continue? -> No
在从local types导入结构体到structures时提示以上问题,导致我无法直接修改结构体
解决方法: windows->Reset hidden messages