【BUUCTF】SimpleRev
收获
熟悉大端序、小端序
熟悉汇编中
str2 db 68h dup(?)
的写法
思路
拖入 IDA,直接查看 main()
函数
逻辑很简单,输入 "q/Q"
,执行语句:(Decry)("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv);
查看函数 (Decry)
注意这里的 src、v9 均为小端存放
而且 text = join(key3, v9)
中传入的参数是 v9 的首地址,即 v9[0]
的值
将 v9[0]
两位一组,逆序输出为字符串:v9[0] = 0x77 6F 64 61 68LL
即:0x68 0x61 0x64 0x6F 0x77,得到 “hadow“
将 src 两位一组,逆序输出为字符串:*src = 0x53 4C 43 44 4ELL
即:0x4E 0x44 0x43 0x4C 0x53,得到 “NDCLS“
根据 key3 的值 “kills“
依据题意,得到拼接处理后的字符串:
text: killshadow
key: ADSFKNDCLS
由于代码:
v5 = strlen(key);
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
}
只是一个初始化操作,并未涉及 flag 的值,直接跑一遍,发现该代码是将 key 由大写变成了小写
得到 key:adsfkndcls
最后的循环采用正向爆破来解决
循环一次读取一个输入的字符,当该字符是大写字母或者小写字母时,就进行操作:
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
如果是空格就跳过,处理下一个,直到全部处理完,遇到 '\n'
,循环结束
最后必须满足:text == str2
这里关于 str2 的定义:
语句 str2 db 68h dup(?)
是指开辟一个 68h 长度的空间,且不进行初始化
脚本
#include <iostream>
#include <string.h>
#include <math.h>
#include <sstream>
using namespace std;
string little_endian(__int64 num, int width_num, int buffer_length, int width_buffer){
std::stringstream ioss; // 定义字符串流
std::string s_temp; // 存放转化后字符
ioss << std::hex << num; // 以十六制形式输出
ioss >> s_temp;
if(width_num > s_temp.size())
{
std::string s_0(width_num - s_temp.size(), '0'); // 位数不够则补0
s_temp = s_0 + s_temp; // 合并
}
std::string s = "0x" + s_temp.substr(s_temp.length() - width_num, s_temp.length()); // 取右width位
string buffer = "";
for(int index=width_num; index>=2; index-=width_buffer){
char sum = 0;
int tmp[width_buffer]; // 存放十六进制的每一位字符转换后对应的十进制数
for(int i=0; i<width_buffer; i++){ // 将width_buffer长度的字符串转换为十进制数,存放到sum
if(s[index]>=97 && s[index]<=102) // 处理a-f
tmp[i] = 9 + s[index] - 96;
else if(s[index]>=65 && s[index]<=70) // 处理A-F
tmp[i] = 9 + s[index] - 64;
else // 处理0-9
tmp[i] = s[index] - 48;
sum = sum + tmp[i] * pow(16,width_buffer-1 -i);
index++;
}
index = index - width_buffer; // 因为前面修改了index,后面还要用index控制循环,所以这里将其还原
buffer += sum; // 将字符sum逆向存储到 buffer字符串
buffer_length--;
}
return buffer;
}
int main() {
__int64 src = 0x534C43444ELL;
__int64 v9[2] = {0x776F646168LL, 0LL};
int v7 = 0LL, v8 = 0, v10 = 0;
string key3 = "kills";
string key1 = "ADSFK";
string s_v9="", s_src="";// hadow NDCLS
s_v9 = little_endian(v9[0],10,5,2);
s_src = little_endian(src,10,5,2);
string text = key3 + s_v9;
string key = key1 + s_src;
cout<<"text: "<<text<<" "<<"key: "<<key<<endl;
int v5 = key.length();
int v2 = 0, v3 = 0;
for (int i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
}
cout<<"key: "<<key<<endl;
for (int i = 0; i < text.length(); ++i) {
for (int j = 32; j < 127; ++j) {
if((j>=65 && j<=90) || (j>=97 && j<=122)){
if(text[i] == (j - 39 - key[v3 % v5] + 97) % 26 + 97){
printf("%c",j);
++v3;
break;
}
}
}
++v2;
}
return 0;
}
结果
KLDQCUDFZO
评论