链接见标题。

这个题其实不需要IDA这些工具。
首先我们先checksec start:

没有防护机制,想想也是,毕竟只是一个start。
接下来我们objdump来看一下汇编代码:

很短小。我们看到了两个int 0x80,这是用来进行系统调用的。
我们用gdb先给0x8048060下断并运行:

接着我们继续执行,直到这里:

我们知道了前面的几个push就是把这一串字符串给送入栈中了。接下来第一个int 0x80应该就相当于write,第二个就相当于read。

执行到这里,我们看到ECX与ESP指向同一片内存。而ESP是栈顶指针,这意味着程序将会往这一片内存执行写入操作。后面那个add操作,让ESP增加20,同时ret。我们知道,ret相当于 pop EIP,所以,执行了add后的ESP指向的内存存储的就是返回地址。
因此我们可以通过覆盖这一片内存来达到控制程序的目的。但是,它们指向的都是栈内存,而栈内存每次运行都不同,因此我们需要动态获取地址。
我们注意到在四个push之后有一个ESP给ECX赋值的操作,然后才调用的write,因此我们猜测它输出的应该就是ECX指向的地方。如果我们的程序在执行完read后能再回到这个地方,我们就能获得read的时候的ESP,我们就可以知道我们应该往哪里注入shellcode了。
注意到mov 操作的地址是:0x8048087,
我们打开终端,然后:

获取到了执行写操作的时候的ESP地址。这时候我们构造shellcode,可以百度到。
shellcode = '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
为什么不能用shellcraft.sh()构造shellcode呢?我也不知道。
接下来我们构造新的payload。
现在还是在写操作,但是我们已经知道了ESP的地址,也就是写操作开始的地址(栈从上往下是从低到高的,写操作是从上往下写的),我们将ESP+0x14的地方保存的地址覆盖成我们的shellcode的开始地址。
payload = 'A' * 20 + p32(leak + 20) +shellcode
为什么要写leak+20呢?因为我们将shellcode写到了leak+20的地方啊:)
所以最后ret的时候EIP就会跳到leak+20这片栈空间,就会执行这里的命令了。
所以最后如下:

运行结果:

最后在home/start/找到了flag:

FLAG{Pwn4bl3_tW_1s_y0ur_st4rt}
另,这个最好写成脚本,因为时间一长服务器会自动断开连接,就得重来。

网友评论