一个简单的CTF小DEMO

一个简单的CTF小DEMO

不说废话 ,开始看代码

1563290467065

main函数的开始提示输入FLAG

1563290577373

输入完FLAG之后进行长度判断 上图中的jnb跳转到跳转到失败输出代码,也就是说FLAG的长度小于0x1E,下面ja跳转到FLAG判断代码。

这两个cmp转换为c代码

1
if(4 < flag < 0x1E)

1563290874171

上图为jnb跳转的位置,输出Sorry,keep trying!,跳转到return

1563291020325

上图为ja跳转的位置loc_401093。

for循环判断输入的 FLAG的前四个字节是否为EIS{,上图中的变量register_header保存的ASSCII码“EIS{”,循环跳出条件为register_header的长度。

1563291253721

​ for循环结束又是一个判断,判断FLAG的第0x1C字节处的ASCII码是否为‘}’,如果不是输出Sorry ,keep trying !并跳转到return,那么0x1C + 1就是FLAG的长度,去掉EIS{},真正参与计算的代码的长度为24。

1563291427190

上图为ja跳转的位置,传入FLAG,调用calc_register_code,判断其返回值,calc_register_code也就是真正的计算函数。

1563291512011

进入calc_register_code

首先判断FLAG是否大于4,如果小于等于4跳转到return。

1563291610231

紧接着又是一个for循环,把FLAG+4之后的数据拷贝一份拷贝到back_str

1563291796614

上图中黄色部分把拷贝出来的back_str最后一个字节赋值为0,也就是将 ‘}’ 修改为0,此时的back_str保存了EIS{….},括号里的内容长度为24字节。

计算部分

1563292006037

for循环部分,如果循环次数大于back_str的长度跳出循环

1563292026464

if判断,在两个cmp中看到如果back_str[i]不是小写字母,则跳到loc_4012FF处,如果是小写字母,将这个字节进行减掉0x20转换为大写字母。

1
2
3
//C伪代码
if('a' <= back_str[i] <= 'z')
back_str[i] -= 0x20

字母转换结束后,在上图的最后一行代码,将var_B0赋值为(var_B0为DWORD类型)1。

1563292351121

紧接着又是一个if判断,这个if判断,首先判断var_B0是否为0,不为0跳转到loc_401340处,然后判断back_str[i]是否为大写字母,如果是大写字母进行加0x20,转换为小写字母。

1
2
3
//C伪代码
if(var_B0 != 0 && 'A' <= back_str[i] <= 'Z')
back_str[i] += 0x20

1563292555155

字母转换之后将转换之后的字节传入到char_calc进行计算。

1563292601289

char_calc将传入的字节进行异或0x55,后在加上0x48返回。

1
2
3
4
5
6
7
//c伪代码
char char_calc(char ch)
{
ch |= 0x55;
ch += 0x48
return ch;
}

1563292724261

char_calc计算之后,将计算的结果和calc_code[i]进行异或计算,最后结果保存到var_AC[i]中。

calc_code 的内容如下

1563292853691

保存完成之后进行第二次for循环。

1563292932569

for循环结束后,将计算出来的结果和1563295477991进行比较,如果一样返回1,否则返回0。

Good Job.

A

1563293861722

1563293876622

最终的注册码

1563293808998

上图中的done_code为注册码。

1571159884917

Author: YuanBi
Link: https://www.basicbit.cn/2018/11/01/2018-11-02 一个简单的CTF小demo/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.