ezret
0x01 题目来源
感谢cgg投喂喵
0x02 思路
先查壳
无壳,64位程序,丢进ida分析一下,找到main函数,给几个关键函数改个名
获取输入flag,然后运行check_constprop_0()
追踪一下check_constprop_0();
切换到汇编
发现ret指令,中断了伪代码分析,调试看看这个循环干了什么
随便输个flag
F7一下,发现循环就是把step1和step2轮流压栈
(部分栈的内容)
分别追踪step1和step2
step1
step2
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;
}