Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yet another shellcode encoder bug in encoders.encoder.printable. #2005

Open
un1c0rn-the-pwnie opened this issue Nov 29, 2021 · 0 comments
Open

Comments

@un1c0rn-the-pwnie
Copy link

un1c0rn-the-pwnie commented Nov 29, 2021

I was trying to create ascii shellcode through encoders.encoder.printable which was producing wrong results but even after seeing the fixes to encoder in #1923 still the encoders.encoder.printable was misbehaving.
In i386 arch i tried this code:

from pwn import *

context.arch = 'i386'

_asm_ = asm(shellcraft.i386.linux.sh())
print(f'ascii_shellcode = {encoders.i386.ascii_shellcode.encode(_asm_)}')
print(f'ascii_shellcode through printable = {encoders.encoder.printable(_asm_)}') 

Results:
ascii_shellcode = b"TX-&!!!-~_``-~~~~P\\%!!!!%@@@@-!!6!-V!~!-~e~<P-.)!!-~~[v-~~~~P-b!!c-~/_~P-!!Q3-!!~~-n4~~P-!!U!-/H~nP-O^@!-~~~>P-7&!!-~~!I-~~.~P-!!!!-!~!!-6~U=P-^!!!-~!`!-~>~PP-!6!!-a~Vf-~~~~P-!!!<-&'k~-~~~~P-\\YY!-~~~}PPPPPPPPPPPPPPPPPPPPP"
[ERROR] No encoders for i386 which can avoid '[^\\x21-\\x7e]' for
    00000000  6a 68 68 2f  2f 2f 73 68  2f 62 69 6e  89 e3 68 01jhh///sh/bin│··00000010  01 01 01 81  34 24 72 69  01 01 31 c9  51 6a 04 59  │····│4$ri│··1·│Qj·Y00000020  01 e1 51 89  e1 31 d2 6a  0b 58 cd 80               │··│·1·j│·X··0000002c

In a patched version of pwntools where #1923 is applied and some other modifications i found that again encoders.encoder.printable was giving wrong results because of a minor mistake in AsciiShellcodeEncoder. The arch variable of Encoder is not being set which results to AsciiShellcodeEncoder not being appened to i386 arch but instead to None. When encoders.encoder.printable is being called in i386 context AsciiShellcodeEncoder is not applied. The patch is trivial just add arch = 'i386' to AsciiShellcodeEncoder.

In addition because i don't want to open a new issue, i will address another one bug in i386XorEncoder here. In line 72 there is no check for the result of xor_pair. If we call for example encode with a lot of restrictions on bad-chars, xor_pair may be not be able to find a satisfying pair to do the job and so returns None. This may be happen through encoders.encoder.printable because it enforces to many restrictions to encode.

from pwn import *

context.arch = 'i386'

_asm_ = asm(shellcraft.i386.linux.sh())

# Same avoid as printable.
avoid = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'

encoders.i386.xor.encode(_asm_, avoid)
...
    a, b = xor_pair(raw_bytes, avoid)
TypeError: cannot unpack non-iterable NoneType object

After testing the above bug to arm arch, i found that the same bug is also present to ArmXorEncoder.

from pwn import *

context.arch = 'arm'

_asm_ = asm(shellcraft.arm.linux.sh())

avoid = set(encoders.encoder.all_chars) - set(encoders.arm.xor.ArmXorEncoder.blacklist)
avoid = set(map(ord, avoid))

encoders.arm.xor.encode(_asm_, avoid)

Results:
    key, xordata = xor_key(raw_bytes, avoid, size=1)
TypeError: cannot unpack non-iterable NoneType object

As a workaround for the above two problems we could check for xor_pair and xor_key if they return None and if they do we can raise a RuntimeError? and continue from encode when we hit a RuntimeError as we currently do for NotImplementedError here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants