EasyRE WriteUp
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 = ecx
ecx++
}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_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!!!继续冲压。
上一篇: 盛大云计算COO加盟美丽说任市场副总裁
下一篇: 10.2.3 基本属性