收获

  • 要能看出 v3 是一个二维字符数组,根据代码:
__int64 v3[4]; // [rsp+18h] [rbp-20h]
v3[0] = "Dufhbmf";
v3[1] = "pG`imos";
v3[2] = "ewUglpt";
  • 要能读懂 *(v3[i % 3] + 2 * (i / 3)) 表示的意思:
    对于二维数组 v3 来说,v3[] 实际代表的也是一个首地址:v3[][0] 的地址,所以 2 * (i / 3) 其实是首地址的偏移,因此 v3[i % 3] + 2 * (i / 3) 代表的是 v3[][] 的地址,所以 *(v3[i % 3] + 2 * (i / 3)) 代表的是 v3[][] 的值,即:字符串(字符数组) v3[] 中的一个字符

  • 在 Python 中,整数类型除法,如果除不断,结果会转化为浮点型,所以在 Python 中数组下标的 2 * (i / 3) 要写成 2 * int (i / 3)

  • 找准 flag 的表示,本题循环中用 *(i + a1) 代表 flag 中的每一个字符,直接根据条件表示出 *(i + a1) 即可


【攻防世界】Reversing-x64Elf-100


思路

IDA 查看 main

攻防世界-Reversing-x64Elf-100 1.png

输入的字符串 s 经过 sub_4006FD(s) 处理后若返回 0,则破解成功

查看 sub_4006FD(s)

攻防世界-Reversing-x64Elf-100 2.png

输入的字符串 s 中的每一个字符经过 for 循环处理后,均必须满足 *(v3[i % 3] + 2 * (i / 3)) - *(i + a1) == 1,否则返回1,破解失败

根据代码:

__int64 v3[4]; // [rsp+18h] [rbp-20h]
v3[0] = "Dufhbmf";
v3[1] = "pG\`imos";
v3[2] = "ewUglpt";

可以判断,v3 是一个二维数组【v3 是一个数组,而 v3 的每一个元素又都是一个字符串(char 数组)】

注意这里条件语句的写法:
*(v3[i % 3] + 2 * (i / 3)) ,* 是加在整体上的,所以 * 表示取 v3[i % 3] + 2 * (i / 3) 这个地址上的值,而 v3 是一个二维数组,所以 v3[i % 3] 代表的其实是一个首地址,即 v3[i % 3][0] 的地址,后面的 2 * (i / 3) 其实是一个偏移量,所以 *(v3[i % 3] + 2 * (i / 3)) 指的是 v3[i % 3][2 * (i / 3)] 的值

a1 是输入的字符串 s 的首地址,每一轮循环中的 *(i + a1) 其实就是 s 中的每一个对应元素,因此求出每一轮 *(i + a1) 的值就是 s 中的每一个元素的值,而 v3 中的值并未发生修改,所以根据 *(v3[i % 3] + 2 * (i / 3)) - *(i + a1) == 1 的条件可得:*(i + a1) = *(v3[i % 3] + 2 * (i / 3)) - 1,即: *(i + a1) = v3[i % 3][2 * (i / 3)] - 1


脚本

C++

#include <iostream>
using namespace std;
int main(){
    string v3[4];
    v3[0] = "Dufhbmf";
    v3[1] = "pG`imos";
    v3[2] = "ewUglpt";
    string flag = "";
    for ( int i = 0; i <= 11; ++i )
    {
        flag += v3[i % 3][2*(i/3)] - 1;
    }
    cout<<flag;
    return 0;
}

Python

checker = ["Dufhbmf", "pG`imos", "ewUglpt"]
flag = ""
for i in range(0, 12):
    flag += chr(ord(checker[i % 3][2 * int(i/3)]) - 1)
print(flag)

结果

Code_Talkers

攻防世界-Reversing-x64Elf-100 3.png