欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EasyRE WriteUp

程序员文章站 2022-05-15 11:26:42
...

题源:XCTF-Reverse进阶-004

0x0 新知识

XOR 常用于置0
XOR 运算可逆

0x1 运行

EasyRE WriteUp
运行提示输入,回车后即退出

0x2 查壳

EasyRE WriteUp

0x3 载入IDA 32bit

EasyRE WriteUp
EasyRE WriteUp
可以知道 sub_401020这个call是printf()
EasyRE WriteUp
因为我还是个小白,并不能像大神们一样看静态汇编代码就完全理解程序逻辑,所以我使用IDA 与 OD动静结合的方式来进行分析。

0x4 关闭ASLR,地址对齐

我是在WIN7下进行测试,所以可以手动关闭ASLR使得程序运行不进行随机加载。
EasyRE WriteUp
使用VIEW辅助查看文件偏移,使用WinHex修改数据。在Win下数据为小端序存储,所以在十六进制文件中将看到 40 81
EasyRE WriteUp
关闭ASLR的目的在于将OD中的地址与IDA中的地址进行对齐方便查看,如果不会修改ASLR还可以通过下API断点进行定位。
EasyRE WriteUp
在IAT中可以看到导入的所有API,我发现了这两个在IDA中出现过的函数,我们要定位程序开始运行的代码段,只要在 scanf 的函数头下断点并通过堆栈回到上一层即可。
EasyRE WriteUp
EasyRE WriteUp

0x5 分析

EasyRE WriteUp
EasyRE WriteUp
ecx被赋值为数组的首地址(char *)
EasyRE WriteUp
经典的字符串数组遍历(说是经典,其实我是调试后才能知道这是取字符串长度,嘿嘿嘿),再来看看IDA中的Graph。
EasyRE WriteUp

edx = ecx + 0x1 
do{
	al = ecx
	ecx++
}while( al&al != 0)
sub ecx,edx
cmp ecx,0x10

最终字符串长度存放在ecx中,长度必须为0x18位

EasyRE WriteUp
这里看到push esipop esi 临时保存esi的状态,可以知道esi是一个临时变量 。xor edx,edx自身与自身进行异或得到结果0x0,mov esi , ebp + ecx - 0x25 可知esi存放了数组的最后一个字符的地址。通过以下计算得到:
arr[0] = ebp - 0x24
arr[0x18-1] = ebp - 0x24 + ecx - 0x1

EasyRE WriteUp
通过这个循环可以看出esi递减,edx递增,将字符串进行逆序操作。

EasyRE WriteUp
紧跟着的循环再次将 edx 寄存器置0,用于循环计次
将每一个元素自增1后与0x6做异或运算后存回
EasyRE WriteUp
比较两个字符串
EasyRE WriteUp

0x6 总结

  1. 输入
  2. 长度限制为0x18 即24个字符
  3. 逆序数组
  4. 每个元素进行 +1 ^ 6 操作
  5. 对比字符串是否相等

0x7 脚本编写

EasyRE WriteUp
异或运算是可逆的,下面是争对1bit的运算结果
EasyRE WriteUp

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
/*
.rdata:00402124	00000012	C	xIrCj~<r|2tWsv3PtI
.rdata:00402137	00000006	C	zndka
*/
int main(){
    string str = "xIrCj~<r|2tWsv3PtIzndka";
    cout << str.length()<<endl;
    string flag = str;
    for(int i = 0; i < str.length() ;i++){
        flag[i] = (str[i] ^ 0x6) - 1;
    }
    reverse(flag.begin(),flag.end());
    cout << flag;
}

EasyRE WriteUp

0x8 尝试IDA一键反编译

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // kr00_4
  signed int v4; // edx
  char *v5; // esi
  char v6; // al
  unsigned int v7; // edx
  int v8; // eax
  __int128 v10; // [esp+2h] [ebp-24h]
  __int64 v11; // [esp+12h] [ebp-14h]
  int v12; // [esp+1Ah] [ebp-Ch]
  __int16 v13; // [esp+1Eh] [ebp-8h]

  sub_401020(&unk_402150, v10);
  v12 = 0;
  v13 = 0;
  v10 = 0i64;
  v11 = 0i64;
  sub_401050((const char *)&unk_402158, (unsigned int)&v10);
  v3 = strlen((const char *)&v10);
  if ( v3 >= 0x10 && v3 == 24 )
  {
    v4 = 0;
    v5 = (char *)&v11 + 7;
    do
    {
      v6 = *v5--;
      byte_40336C[v4++] = v6;
    }
    while ( v4 < 24 );
    v7 = 0;
    do
    {
      byte_40336C[v7] = (byte_40336C[v7] + 1) ^ 6;
      ++v7;
    }
    while ( v7 < 0x18 );
    v8 = strcmp(byte_40336C, (const char *)&unk_402124);
    if ( v8 )
      v8 = -(v8 < 0) | 1;
    if ( !v8 )
    {
      sub_401020("right\n", v10);
      system("pause");
    }
  }
  return 0;
}

可以发现,获取长度、逆序等,如果一开始直接看IDA的反编译结果效率会更高,虽然代码看着有点奇怪…慢慢适应吧!我也是今天刚刚安装好IDA!!!继续冲压。

相关标签: 程序逆向之美