IDA反编译的几个注意和技巧

IDA逆向程序的经验总结

  • 关于一些类型转换以及指针和地址的总结
  • 关于F5汇编代码不能转成c的伪代码的几个问题总结
    • 1.jmpout的问题
    • 2.positive sp value has been found 的问题
    • 3.call analysis failed
  • 对于浮点数的逆向思路
  • 对于ARM汇编的一些思路和技巧
  • 对单片机项目的逆向要点
  • IDA 反编译一些可变参数的技巧和总结
    • C语言中对可变参数的读写依赖于宏va_start、va_arg和va_end
    • 还有一种方法不用去使用定义的都参数的宏也能去读取参数
    • IDA 识别可变参数

关于一些类型转换以及指针和地址的总结

最可以拿来当教训的应该是 hide cast 功能
IDA反编译的几个注意和技巧_第1张图片
如果隐藏了,就是这样的
IDA反编译的几个注意和技巧_第2张图片
如果SaveAShouldShowStreamIndex是char类型的数组,那会怎么样呢,一次取一个字节和取四个字节就完全不一样了.当然如果你再逆向的时候就已经知道了这个数组的类型那就没问题,但是也应该注意没到必要的时候不要Hide Casts ,虽然你的代码会被很多类型转换搞得头晕,但是关掉真的影响你的逆向准确性.

关于F5汇编代码不能转成c的伪代码的几个问题总结

1.jmpout的问题

jumpot
IDA反编译的几个注意和技巧_第3张图片
如果遇上jumpout的话,一般是只能动态调试去跟踪调试代码.很少能将jumpOut的汇编修改成能反出伪C的形式.

2.positive sp value has been found 的问题

IDA反编译的几个注意和技巧_第4张图片
出现这个问题一般都是能解决的
这个请参考这个帖子:
https://blog.csdn.net/u010334666/article/details/82937413

3.call analysis failed

IDA反编译的几个注意和技巧_第5张图片
这种一般是函数内部的参数没有解析正确,所以如果想正确解析,需要读取去修改函数内部调用函数的参数.
参考帖子: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标识
IDA反编译的几个注意和技巧_第6张图片
临时变量,在使用的时候用什么寄存器标识
IDA反编译的几个注意和技巧_第7张图片
暂时先想到这些,以后再补充

对单片机项目的逆向要点

需要掌握一定的单片机开发知识.
很多地方涉及到一些硬件的接口和屏幕显示的接口,都是以地址的形式表示,如:0x20004F64,0x20005014 ,0x64000400 ,0x4001300等的地址
IDA反编译的几个注意和技巧_第8张图片
IDA反编译的几个注意和技巧_第9张图片

IDA反编译的几个注意和技巧_第10张图片
看到这种地址上的赋值,就需要去参考手册了
IDA反编译的几个注意和技巧_第11张图片

IDA 反编译一些可变参数的技巧和总结

要IDA 能正确识别出可变参数的函数的参数 首先要清楚定位到可变参数前最后一个确定的参数 这样IDA才能识别出来

C语言中对可变参数的读写依赖于宏va_start、va_arg和va_end

这三个宏的定义如下:

  1. void va_start(va_list ap,
    last);//取第一个可变参数(如上述printf中的i)的指针给ap,last是函数声明中的最后一个固定参数(比如printf函数原型中的*fromat);

  2. type va_arg(va_list ap,
    type);//返回当前ap指向的可变参数的值,然后ap指向下一个可变参数;type表示当前可变参数的类型(支持的类型位int和double);

  3. 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 


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;
}

可以看出来 既识别不对参数 也没认出这是可变参数
然后手动修改函数参数
IDA反编译的几个注意和技巧_第12张图片
修改两个地方:
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;
}

你可能感兴趣的:(逆向,破解,单片机,指针)