本文主要是介绍EasyRE WriteUp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 0x0 新知识
- 0x1 运行
- 0x2 查壳
- 0x3 载入IDA 32bit
- 0x4 关闭ASLR,地址对齐
- 0x5 分析
- 0x6 总结
- 0x7 脚本编写
- 0x8 尝试IDA一键反编译
题源:XCTF-Reverse进阶-004
0x0 新知识
XOR 常用于置0
XOR 运算可逆
0x1 运行
运行提示输入,回车后即退出
0x2 查壳
0x3 载入IDA 32bit
可以知道 sub_401020这个call是printf()
因为我还是个小白,并不能像大神们一样看静态汇编代码就完全理解程序逻辑,所以我使用IDA 与 OD动静结合的方式来进行分析。
0x4 关闭ASLR,地址对齐
我是在WIN7下进行测试,所以可以手动关闭ASLR使得程序运行不进行随机加载。
使用VIEW辅助查看文件偏移,使用WinHex修改数据。在Win下数据为小端序存储,所以在十六进制文件中将看到 40 81
关闭ASLR的目的在于将OD中的地址与IDA中的地址进行对齐方便查看,如果不会修改ASLR还可以通过下API断点进行定位。
在IAT中可以看到导入的所有API,我发现了这两个在IDA中出现过的函数,我们要定位程序开始运行的代码段,只要在 scanf 的函数头下断点并通过堆栈回到上一层即可。
0x5 分析
ecx被赋值为数组的首地址(char *)
经典的字符串数组遍历(说是经典,其实我是调试后才能知道这是取字符串长度,嘿嘿嘿),再来看看IDA中的Graph。
edx = ecx + 0x1
do{al = ecxecx++
}while( al&al != 0)
sub ecx,edx
cmp ecx,0x10
最终字符串长度存放在ecx中,长度必须为0x18位
这里看到push esi
和pop esi
临时保存esi的状态,可以知道esi是一个临时变量 。xor edx,edx
自身与自身进行异或得到结果0x0,mov esi , ebp + ecx - 0x25
可知esi存放了数组的最后一个字符的地址。通过以下计算得到:
arr[0] = ebp - 0x24
arr[0x18-1] = ebp - 0x24 + ecx - 0x1
通过这个循环可以看出esi递减,edx递增,将字符串进行逆序操作。
紧跟着的循环再次将 edx 寄存器置0,用于循环计次
将每一个元素自增1后与0x6做异或运算后存回
比较两个字符串
0x6 总结
- 输入
- 长度限制为0x18 即24个字符
- 逆序数组
- 每个元素进行 +1 ^ 6 操作
- 对比字符串是否相等
0x7 脚本编写
异或运算是可逆的,下面是争对1bit的运算结果
#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;
}
0x8 尝试IDA一键反编译
int __cdecl main(int argc, const char **argv, const char **envp)
{unsigned int v3; // kr00_4signed int v4; // edxchar *v5; // esichar v6; // alunsigned int v7; // edxint 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!!!继续冲压。
这篇关于EasyRE WriteUp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!