收获

  • 处理 JUMPOUT 花指令

  • 正向爆破时,如果同时遇到两个未知变量的处理方法
    本题对于条件 Str1[i] = (Str1[i] + Str1[(i * i + 123) % 21]) % 96 + 32 无法进行常规的正向爆破


【NSSCTF】jump_by_jump_revenge


思路

将程序拖入 32位 IDA,查看 main 函数

NSSCTF-jump_by_jump_revenge1.png

对 main 函数 F5 反编译后 JUMPOUT

NSSCTF-jump_by_jump_revenge2.png

在 IDA View-A 中定位 main

NSSCTF-jump_by_jump_revenge3.png

在 main 中未发现花指令,根据 jmp _main_0 跟进到 main_0 的位置

NSSCTF-jump_by_jump_revenge4.png

在 main_0 中 jmp short loc_4118D2 后,到 loc_4118D2 中 jnz short near ptr loc_4118DA+2 跳转到 loc_4118DA
而 loc_4118DA 中 jmp near ptr 0C086A4CCh 跳转到无效的地址使得 main 无法被 IDA 正确编译

选中 jmp near ptr 0C086A4CCh,使用快捷键 D 转换为硬指令:

NSSCTF-jump_by_jump_revenge5.png

选中 db 0E9h,右键 -> Patching -> Change byte,将开头的 E9 改为 90

NSSCTF-jump_by_jump_revenge6.png

选中 db 90h,按快捷键 C 将硬指令转换为代码

NSSCTF-jump_by_jump_revenge7.png

在 main_0 函数起始处按快捷键 P,重新生成函数

NSSCTF-jump_by_jump_revenge8.png

此时 main 函数已经被成功修复:

NSSCTF-jump_by_jump_revenge9.png

进入 main_0 函数:

NSSCTF-jump_by_jump_revenge10.png

根据条件 j_strcmp(Str1, "~4G~M:=WV7iX,zlViGmu4?hJ0H-Q*") 可以判断,还原后的 Str1 就是 flag

① 这里采用了余数的特点:
Str1[i] = Str1[i] % 96 + Str1[(i * i + 123) % 21] + 32
Str1[i] = Str1[i] % 96 + Str1[(i * i + 123) % 21] - 96 + 32

② 变换得到刚开始未处理过的 Str1[i] 取余后的结果,即:
Str1[i] % 96 = Str1[i] - 32 - Str1[(i * i + 123) % 21]
Str1[i] % 96 - 96 = Str1[i] - 32 - Str1[(i * i + 123) % 21]

③ 要得到初始的 Str1[i] 的值,只需将 Str1[i] % 96Str1[i] % 96 - 96 的结果加上 n 个 96,如果加上 n 个 96 后的结果在 32 ~ 127 范围内,那么这个结果就是初始的 Str1[i] 的值

即:只需要将 Str1[i] - 32 - Str1[(i * i + 123) % 21] 的结果加上 n 个 96 即可,取位于 32 ~ 127 之中的结果


脚本

#include <iostream>  
#include <string.h>  
using namespace std;  
  
int main(){  
    string Str1 = "~4G~M:=WV7iX,zlViGmu4?hJ0H-Q*";  
  
    for (int i = 28; i >= 0; --i ){  
        Str1[i] = Str1[i] - 32 - Str1[(i * i + 123) % 21];  
        if (Str1[i] < 32 || Str1[i] > 126){  
            for (int j = 0; j < 5; ++j) {  
                Str1[i] += j * 96;  
                if(Str1[i] >= 32 && Str1[i] <= 126)  
                    break;  
            }  
        }  
    }  
  
    for (int i = 0; i < 29; ++i) {  
        printf("%c",Str1[i]);  
    }  
    return 0;  
}

结果

NSSCTF{Jump_b9_jump!_r3V3n9e}

NSSCTF-jump_by_jump_revenge11.png