Writeup: Silent Authenticator (Malops.io)
Challenge Link: Silent Authenticator Tools Used: IDA Pro, CyberChef, and Reverser.space for collaborative reverse engineering.
Introduction
Welcome to my writeup for the Silent Authenticator challenge from Malops.io. In this challenge, we are tasked with reverse engineering a trojanized Linux Pluggable Authentication Module (PAM) (pam_unix.so). The objective is to uncover its hidden backdoor mechanisms, credential harvesting logic, and persistence methods.
To tackle this binary, I used Reverser.space, which provided a seamless environment for collaborative reverse engineering, allowing for synchronized function renaming, variable type mapping, and dynamic analysis. Below is a step-by-step breakdown of our analysis, detailing the answers to all 35 challenge questions.
Question 1
The malware hides sensitive strings using encryption. By analyzing the decryption function, what is the single-byte XOR key stored at offset 0x00 in each encrypted string table entry?
0x**
First, we need to locate the string encryption function. Starting from the exported function pam_sm_authenticate, we can see a function (FUN_001032a0) that takes an index and accesses a data structure at DAT_0030c042. We can rename this function to mw_string_enc, with param_1 as the index and param_2 as the out_buffer.
The disassembly shows the calculation lVar4 = (ulong)index * 0x10;, meaning the offset size for each entry is 0x10 (16 bytes). By looking at the data at DAT_0030c042, we can see that the first byte (which serves as the base XOR key) is 0x54.
Answer: 0x54
Question 2
The decryption function calculates the table entry offset by shifting the index. What is the shift value used in the ‘shl’ instruction to multiply the index by the entry size?
*
The shift value can be found in the instruction SHL RDI, 0x4 at address 0x1032aa. A logical left shift by 4 is mathematically equivalent to multiplying by 16 (0x10), which matches the 16-byte size of the string entry structure.
Answer: 0x4
Question 3
Each encrypted string entry contains a pointer to the actual encrypted data. At what byte offset within the 16-byte entry structure is this pointer located?
*
By reversing the memory layout, we can define the C structure as follows:
struct StringEntry // sizeof=0x10
{
uint8_t base_key; // Offset 0
uint8_t padding1; // Offset 1
uint16_t length; // Offset 2
uint32_t padding2; // Offset 4
char *encrypted_text; // Offset 8
};
According to this structure, the pointer to the encrypted text is located at byte offset 8.
Answer: 8
Question 4
The string length field is stored as a 16-bit value within each entry. At what byte offset is the length field located in the entry structure?
*
Based on the StringEntry structure defined in the previous question, the 16-bit length field is located at byte offset 2.
Answer: 2
Question 5
Analyzing the encrypted strings table, how many total encrypted string entries does the malware store?
*
By examining the data section at DAT_0030c040, we can count exactly 7 consecutive StringEntry blocks defined in memory.
Answer: 7
Question 6
The first encrypted byte of the backdoor password. What is this encrypted byte value?
0x**
The encryption logic retrieves the base key from the structure and XORs it with the character’s index to generate a rolling key. The pseudocode looks like this:
int i = 0;
do {
uint8_t current_key = entry->base_key ^ i;
out_buffer[i] = entry->encrypted_text[i] ^ current_key;
i++;
} while (i < entry->length);
Using this CyberChef recipe, we can replicate this logic by supplying the encrypted hex array and applying a rolling XOR with the base key 0x54 and an index byte array. The first encrypted byte evaluates to 0x6d.
Answer: 0x6d
Question 7
What is the hardcoded master password that bypasses authentication for any user?
**************
After decrypting the first string entry (Index 0), the resulting plaintext reveals the hardcoded backdoor password.
Answer: 97@I7OEaF*5a92
Question 8
What libc function does the malware call to compare the user-supplied password against the decrypted backdoor password?
******
We can trace the output buffer of the first string decryption call (mw_string_enc with index 0, yielding the master_passwd). Following the cross-references to this buffer reveals a call to strcmp(master_passwd, local_58);, where the user-supplied password is compared to the master password.
Answer: strcmp
Question 9
Before checking the backdoor password, the malware retrieves the username using a PAM API function. What is the name of this function?
***_***_****
The malware calls pam_get_user to retrieve the target username attempting to authenticate. This is a standard Linux PAM API function.
Answer: pam_get_user
Question 10
After decrypting string index 2, what is the full file path where the malware stores harvested credentials?
/***/***/.***.***
Decrypting the string at index 2 yields the hidden file path where the backdoor logs harvested usernames and passwords.
Answer: /usr/bin/.dbus.log
Question 11
Before writing credentials, the malware encodes them as hexadecimal. What sprintf format specifier is used for this hex encoding?
%**
By tracing the file writing operations for index 2 (/usr/bin/.dbus.log), we observe the malware iterating through the password bytes and formatting them using sprintf with the %2X specifier, which converts the string into uppercase hexadecimal format.
Answer: %2X
Question 12
The credential log uses a specific format string for entries. What is the prefix text that appears before the encoded username in each log entry?
***** **************->
By examining the hardcoded strings passed into the logging format function, we can see the exact prefix used for every log entry.
Answer: error ServiceUnknown->
Question 13
What separator string appears between the encoded username and encoded password in the log format?
*
Looking at the full format string error ServiceUnknown->%s : %s\n, the separator between the first %s (encoded username) and the second %s (encoded password) is a colon surrounded by spaces, but the core punctuation mark is the colon.
Answer: :
Question 14
When opening the credential log for writing new entries, what fopen mode string is used?
*
The fopen call uses the mode "a" (opened_stream = fopen(filename: write_filename__1, modes: "a");). This opens the file in append mode, ensuring existing logs are not overwritten.
Answer: a
Question 15
After decrypting string index 3, what is the full path to the legitimate file used as a timestamp reference?
/***/***/id
Decrypting the string at index 3 reveals the path to a legitimate system binary. The malware uses this file’s timestamp to disguise its own malicious files (timestomping).
Answer: /usr/bin/id
Question 16
After decrypting string index 4, what Unix command is used to copy the timestamp from the reference file? (First word only)
*****
Decrypting the string at index 4 provides the full command: touch -r /usr/bin/id /usr/bin/.dbus.log. The first word is the Unix utility used to modify file timestamps.
Answer: touch
Question 17
The timestamp manipulation command uses what flag to reference another file’s timestamp?
-*
From the decrypted command touch -r /usr/bin/id /usr/bin/.dbus.log, the -r (reference) flag is used to apply the timestamp of /usr/bin/id to the log file.
Answer: -r
Question 18
What is the full path to the hidden directory where the malware looks for scripts to execute?
/***/*****/.*******/
Decrypting the string at index 1 reveals the hidden directory path where the malware searches for additional payloads to run.
Answer: /var/spool/.network/
Question 19
What libc function is called to open the hidden directory for reading its contents?
*******
The malware uses the standard libc directory stream function opendir to open the /var/spool/.network/ directory.
Answer: opendir
Question 20
What libc function is called in a loop to iterate through each file in the hidden directory?
*******
Inside the opendir loop, the malware continuously calls readdir to iterate through all the files present in the hidden directory.
Answer: readdir
Question 21
The malware checks the d_type field to identify regular files. What decimal value indicates a regular file (DT_REG)?
*
The code checks the d_type field of the dirent structure. It compares it against the decimal value 8, which corresponds to the DT_REG macro in C (indicating a regular file).
Answer: 8
Question 22
After decrypting string index 5, what Unix utility is prepended to commands to run them detached from the terminal?
*****
Decrypting the string at index 5 reveals the utility used to run dropped scripts in the background, ignoring hangup signals.
Answer: nohup
Question 23
After decrypting string index 6, what is the full output redirection string appended to executed commands?
>/***/**** *>&* &
Decrypting the string at index 6 reveals the standard output redirection payload appended to the command to suppress output and run it as a background job.
Answer: >/dev/null 2>&1 &
Question 24
What libc function is used to execute the constructed command string containing nohup and the script path?
******
After concatenating nohup, the script path, and the redirection string using sprintf, the malware passes the resulting buffer to the standard libc function system for execution.
Answer: system
Question 25
Before logging credentials, the malware checks if it has root privileges. What libc function returns the effective user ID?
*******
To verify if the compromised process currently has root privileges (which allows for stealthier logging and execution without permission errors), the malware calls geteuid.
Answer: geteuid
Question 26
What return value from geteuid indicates the process is running as root?
*
In Unix-like systems, a return value of 0 from geteuid() indicates that the process is running as the root user.
Answer: 0
Question 27
What libc function is called to check if the credential log file already exists before writing?
******
Before attempting to read or append to the credential log, the malware verifies the file’s existence and permissions using the access libc function.
Answer: access
Question 28
What is the name of the main PAM export function that contains all the backdoor logic?
pam_sm_************
The core backdoor logic is injected directly into the standard PAM authentication routine. Throughout this process, we have been reverse engineering this specific exported function.
Answer: pam_sm_authenticate
Question 29
How many PAM module functions (pam_sm_*) are exported by this malicious module?
*
By looking at the Export Address Table (EAT) of the compiled shared object, we can see exactly 6 standard PAM Service Module (pam_sm_*) functions exported by this library.
Answer: 6
Question 30
What string identifier is passed to pam_set_data to store the authentication return value?
****_*******_******
We can observe a call to pam_set_data used to store state or credential pointers. The string identifier passed into this function is clearly visible in the decompiled code.
Answer: unix_setcred_return
Question 31
What PAM internal data identifier string is used when prompting for and storing the user’s password?
-UN**-****
When wrapping the PAM prompt mechanism to grab the password, the malware uses a specific internal identifier string (visible in plaintext) to store/retrieve the password item.
Answer: -UN*X-PASS
Question 32
When authentication fails, pam_fail_delay is called. What is the delay value in microseconds passed to this function?
*******
By cross-referencing calls to pam_fail_delay inside the authentication failure logic, we can see the hardcoded delay parameter passed to it.
Answer: 2000000
Question 33
What is the size in bytes of the stack buffer used to construct command strings before execution? (Decimal)
***
By tracing the destination buffer of the sprintf call that builds the system command, we can find an associated memset operation that initializes it. The memset size parameter is 0x200.
Answer: 512
Question 34
When reading lines from the credential log, what is the maximum line length passed to fgets?
0x***
When the malware reads existing lines from the credential log using fgets, the maximum buffer length parameter passed to the function is 0x200.
Answer: 0x200
Question 35
When updating an existing credential log entry, the malware uses a temporary file. What single-character filename is used for this temporary file?
*
If the malware needs to recreate or update the log file, it writes to a temporary file first and then calls rename(). The temporary filename is a single-character string visible in the disassembly.
Answer: a