ezret

Cia1lo發表於2024-06-17

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}