一开始看到不少溢出,但是由于有canary这些都无法用。还是从头开始读程序。
程序包含3块:
- 第一块读入用户名和salt盐在盐后加上后台的key得到密钥再通过密钥算出密码。
- 通过用户名和密码登录,用户名是admin且验证成功后显示flag
- 没有用
很显然如果第1步让用admin就好办了。然无。
这个盐有个溢出:盐长度不足7位时会补成7位后边加7位key。如果超过7位则用的key就会相应减少。当盐为13位时就只用到第1位key。那么就可以很容易的爆破出key的值。然后用des算出密码就ok了。
unsigned __int64 __fastcall sub_400A04(__int64 a1, _QWORD *a2)
{
char v3[140]; // [rsp+20h] [rbp-B0h] BYREF
int fd; // [rsp+ACh] [rbp-24h]
char dest[16]; // [rsp+B0h] [rbp-20h] BYREF
char v6[8]; // [rsp+C0h] [rbp-10h] BYREF
unsigned __int64 v7; // [rsp+C8h] [rbp-8h]
v7 = __readfsqword(0x28u);
*a2 = 0LL;
*(_QWORD *)dest = 0LL;
fd = open("key", 0);
if ( strlen(byte_6020C0) <= 6 ) //当salt为13位时,只用到1位key 可依次爆破key
strncpy(&byte_6020C0[strlen(byte_6020C0)], "aaaaaaa", 7 - strlen(byte_6020C0));
strncpy(dest, byte_6020C0, strlen(byte_6020C0));
read(fd, &dest[strlen(byte_6020C0)], 7uLL);
dest[14] = 0;
close(fd);
DES_string_to_key(dest, v6);
DES_set_key(v6, v3);
DES_ecb_encrypt(a1, a2, v3, 1LL);
return __readfsqword(0x28u) ^ v7;
}
另外就是写程序算des不一定容易,可以直接把原程序patch一下让他不检查admin用户名,这样通过原程序就可以得到密码。
from pwn import *
local = 1
if local == 1:
p = process('./pwn')
else:
p = remote('node4.buuoj.cn', 28546)
elf = ELF('./pwn')
context.arch = 'amd64'
def getkey(salt):
p.sendlineafter(b"What would you like to do? ", b'1')
p.sendlineafter(b"Enter username:", b's')
p.sendlineafter(b"Enter salt:", salt)
p.recvuntil(b'Your password is: ')
return p.recv(16)
def password():
tp = process('./pwn_local')
tp.sendlineafter(b"What would you like to do? ", b'1')
tp.sendlineafter(b"Enter username:", b'admin')
tp.sendlineafter(b"Enter salt:", b'aaaaaaa')
tp.recvuntil(b'Your password is: ')
return tp.recv(16)
def getflag(password):
p.sendlineafter(b"What would you like to do? ", b'2')
p.sendlineafter(b"Enter username:", b'admin')
p.sendlineafter(b"Enter password:", password)
return p.recv()
key = b''
for i in range(13,6,-1):
salt = b'A'*i
tmpkey = getkey(salt)
print(tmpkey)
for j in range(0x21,0x80):
tmp = getkey(salt+key+p8(j)) #逐位缩短的salt+key已知部分+猜 密码相同即为正确的key
if tmp == tmpkey:
key += p8(j)
print('key:', key)
break
open('key', 'wb').write(key)
password = password() #利用本地程序运算求密码
print(password)
context.log_level = 'debug'
print(getflag(password))
pause()