攻防世界RE
Reversing-x64Elf-100
追踪main 函数发现
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
追踪sub_4006FD函数可得
1 | __int64 __fastcall sub_4006FD(__int64 a1) |
1 | 这段代码是在进行一个条件判断,如果条件满足,则返回 1;否则继续执行。具体来说,该语句检查 v3 是一个长度为 3 的字符指针数组(或者是一个包含三个字符数组的二维数组),其中第 i % 3 个元素是一个字符数组,长度为偶数。并且,在索引为 i / 3 的位置上的字符减去地址为 i + a1 的字符的 ASCII 码的差不等于 1。 |
1 | key1="Dufhbmf" |
666
没有加壳
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
1 | memset(s, 0, 0x1EuLL) 是一个内存操作函数,用于将内存块 s 的前 0x1E 个字节设置为0。具体来说,它的参数包括: |
追踪函数encode,发现关键代码
1 | int __fastcall encode(const char *a1, __int64 a2) |
1 | *(_BYTE *)(a2 + i) 是一个内存访问操作,用于获取位于内存地址 (a2 + i) 的字节值。 |
读取key的值为18,将enflag的ascii码转为10进制数。
脚本:
1 | str = [ |
easyRE1
没加壳
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
一眼就看出来
lucknum
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
一眼看出来
reverse_re3
1 | __int64 sub_940() |
追踪 sub_86C();函数,发现数组
将数据导出
删去前后的数组名和括号
使用脚本处理为3个15*15的矩阵
1 | # 打开文本文件 |
1 | [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] |
“3”是起点,“4”是终点,“1”是可走的,“0”是不可走的
最后将三个迷宫的解法,并在一起
1 | ddsssddddsssdssdddddsssddddsssaassssdddsddssddwddssssssdddssssdddss |
md5加密一下得到flag
1000Click
shift + F12搜索得到很多flag,发现只有一个调用的,该flag即为正确的flag
crypt
下载附件得到crypt.exe,拖入exeinfope分析得64bit,无壳。拖入ida64,打开搜索main函数,f5反编译,发现了对字符串Str的复制。看到下方和Str有关联的是v9,点击sub_140001120,以及sub_140001240(v9, (__int64)v10, v4);可以得到两段函数。
那么经过分析,密钥就是Str字符串。看完两段函数后,返回main函数,最终找到if ( ((unsigned int8)v10[i] ^ 34) != (unsigned int8)byte_14013B000[i] ),这里对byte_14013B000[i] 进行了异或处理。自此我们可以判断加密方式是RC4加密
*对明文使用同一个密钥异或两次最后是得到原文的。
因此只需要对byte_14013B000[i]进行rc4解密就可以了。解密脚本如下:
1 | unsigned char ida_chars[] = |
解密运算:
1 | from Cryptodome.Cipher import ARC4 |
happyctf
无壳拖入IDA
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
1 | int __thiscall sub_403B70(void *this, char a2) |
此代码主要实现了对输入的字符的每一个字母进行与或运算,最终与
1 | rxusoCqxw{yqK`{KZqag{r`i |
进行对比,所以直接对字符串每个字母进行与或即可。
1 | str = "rxusoCqxw{yqK`{KZqag{r`i" |
xxxorrr
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 惜缘怀古的博客!