Can you get authentication from this server?
Download : http://pwnable.kr/bin/login
Running at : nc pwnable.kr 9003
反编译main函数
通过main函数的第21行我们知道,解码之后的字符串也被存放在了input指向的内存单元中。同时我们知道,input在bss段。
反编译Base64Decode函数
反编译auth函数
通过查看auth函数,我们发现很难通过正常的程序执行流程来通过验证。但是,问题的切入点也是这个auth函数。我们发现在auth函数的地7行:
memcpy(&v4, &input, a1).也就是说,把a1长度的字符串从一个地址(&input)复制到另一个地址(&v4).
双击input
我们发现input存在于bss段,也就是说,input是未初始化的全局变量。
我们不妨画出auth函数的栈帧结构:
我们可以知道,在执行完auth函数第7行的memcpy函数之后,如果假设input指向的内容有12个字节。那么上图中的内存单元中的数据将会被覆盖:
也就是说,之前保存的main函数的ebp被覆盖了,变成了一个新的值。我们不妨把这个设置为input的地址。这样的话,假设之前input地址处的内容如下:
那么input地址也同时是main函数的ebp,那么
那么在main函数执行完毕之后,就可以执行payload2对应的地址处的指令了。
所以,本题的精髓在于,通过溢出auth函数的栈帧,来设置auth中保存的main函数的ebp为input变量的地址(该地址在bss段中,并且之前输入的内容也保存与input中),今儿通过之前input变量中的内容,来覆盖main函数执行完毕之后的eip,从而控制程序的执行。
从0x08049284处开始执行,相当于为system传递参数。所以payload2用于覆盖main函数的eip,payload3用于覆盖main函数的ebp。该ebp设置为input的地址,即0x0811eb40。
from pwn import *
from zio3 import p32
ready_call_system = 0x8049284
input_or_main_ebp = 0x811eb40
payload = 'abcd'.encode('ascii') + p32(ready_call_system) + p32(input_or_main_ebp)
print(payload)
payload = b64e(payload)
print(payload)
所以,输入YWJjZISSBAhA6xEI即可通过。
为了验证我们的payload,我们把YWJjZISSBAhA6xEI通过base64解码之后,使用hexdump查看解码之后的内容对应的十六进制数据。