ezret

0x01 题目来源

感谢cgg投喂喵

0x02 思路

先查壳
image

无壳,64位程序,丢进ida分析一下,找到main函数,给几个关键函数改个名
image
获取输入flag,然后运行check_constprop_0()
追踪一下check_constprop_0();
image
切换到汇编image
发现ret指令,中断了伪代码分析,调试看看这个循环干了什么
随便输个flag
image
F7一下,发现循环就是把step1和step2轮流压栈
image
(部分栈的内容)
分别追踪step1和step2

step1

image

step2

image

step1中先将rax压栈,然后调用rand,之后使用rax和flag中的字符作异或运算,这里要注意,进行异或运算的是eax即32位寄存器,之后pop rcx,使得rcx等于之前的rax的值,比较cl与al的值,如果相同则进行key+=1(此处使用的是rax与rcx低八位,即char类型的变量)

step2即对rax进行异或运算,作为step1的前置步骤

0x03 解密

使用两个变量以及一个数组(数组为long long类型)
先将int类型变量v1进行异或运算,然后将其低八位赋值给char类型v2,之后使用rand函数给v1赋值,之后进行v1与v2的异或运算,即为flag的字符
(rand函数实际上是伪随机数,被rand卡了一下O.o)

0x04 EXP

#include <iostream>

long v1;
char v2;
int key;
char flag[27];

int main() {
    using namespace std;
    long long num[26]={0x40CF,
            0x8012,
            0x809C,
            0x4000B9,
            0x830,
            0x451,
            0x20009A,
            0x10069,
            0x848,
            0x8005E,
            0x80055,
            0x404E,
            0x80001A,
            0x8B3,
            0x40066,
            0x200003,
            0x2002B,
            0x10095,
            0x20C5,
            0x800029,
            0x2000FB,
            0x1045,
            0x800AC,
            0x100090,
            0x404F,
            0x204F};
    
    for (int i = 25; i >=0; --i)
    {
        for (int j = i; j <=25 ; ++j)
        {
            v1^=num[j];
        }
        v2=(char)v1;
        v1=rand();
        flag[key++]=v2^v1;
        v1=v2;
    }

    printf(flag);
    return 0;
}
flag{testflag1145141919810}
posted @ 2024-06-17 00:06  Cia1lo  阅读(25)  评论(0编辑  收藏  举报