Skip to main content
11 min read Intermediate Desktop

Thick Client Penetration Testing Checklist

A comprehensive, checkable list for testing Windows, Java, and .NET thick client applications.

Each section ends with a "Handy tools and commands" block with copy-paste examples. Replace placeholders such as app.exe, <PID>, and <host> with your target's values.


Table of Contents

  1. Information Gathering
  2. GUI Testing
  3. File System Testing
  4. Registry Testing
  5. Network and Traffic Testing
  6. Binary and Assembly Protection Testing
  7. Memory Testing
  8. Reverse Engineering and Code Testing
  9. Authentication and Authorization
  10. Data Storage and Secrets
  11. Backend Communication and Injection
  12. DLL and Process Security
  13. Cryptography
  14. Logging and Error Handling
  15. Software Update Mechanism
  16. Inter-Process Communication (IPC)
  17. Privilege Escalation and Persistence
  18. Protocol Handlers and Argument Injection
  19. Framework-Specific Tests
  20. Local and Embedded Servers
  21. Licensing and Business Logic
  22. Reporting

1. Information Gathering

  • Identify the architecture (two-tier or three-tier)
  • Identify the language and framework (.NET, Java, C/C++, Electron, Python)
  • Detect packer, compiler, and protections with Detect It Easy or CFF Explorer
  • Identify all network endpoints and protocols (HTTP/S, TCP, UDP, FTP/S)
  • Map every input and entry point (forms, files, IPC, network, command line)
  • Observe the process, child processes, and loaded modules
  • Identify the authentication and authorization mechanisms
  • Note the install location, config files, and data folders
  • Check whether the app runs with admin or elevated privileges
  • Run Strings on the binary for quick wins (URLs, keys, paths)

Handy tools and commands:

# Identify language, packer, and compiler
diec.exe app.exe # Detect It Easy (CLI)

# Pull interesting strings (Sysinternals Strings)
strings.exe -n 8 app.exe | findstr /i "http https password key token secret connectionstring"

# See loaded modules, child processes, handles
# GUI: Process Explorer (procexp64.exe) -> select process -> lower pane (DLLs / Handles)

# Live network endpoints for the process
netstat -ano | findstr <PID>

# Confirm privilege level
# GUI: Process Explorer column "Integrity" (Medium / High / System)

2. GUI Testing

  • Reveal hidden form objects
  • Enable disabled controls and buttons
  • Unmask password fields
  • Look for sensitive information shown in the UI
  • Bypass access controls using intended GUI features
  • Test client-side input validation and sanitization
  • Try privilege escalation (unlock admin features as a normal user)
  • Try payment, price, or quantity manipulation
  • Check improper error handling in the UI
  • Inspect the UI tree with Spy++, WinSpy++, or Snoop WPF

Handy tools and commands:

Spy++ : inspect and edit Win32 window styles (unhide, enable controls)
WinSpy++ : reveal masked password fields, change control styles
Snoop / snoopwpf : inspect and edit live WPF visual tree and bindings
Window Detective : view and change window properties
BulletsPassView : reveal password-box contents (standard Win32 fields)

Tip: to enable a disabled button, clear its WS_DISABLED style in Spy++/WinSpy++.
Tip: to unmask a password box, remove the ES_PASSWORD style or change the password char.

3. File System Testing

  • Check file and folder permissions (read and write for low-privilege users)
  • Look for sensitive data in config files (app.config, .ini, .xml, .json)
  • Look for hardcoded credentials, keys, or connection strings on disk
  • Look for cleartext storage of sensitive data
  • Check temp files and cache for leaked data
  • Check local databases (SQLite and others) for sensitive data
  • Verify code signing and strong naming
  • Test file and content replacement
  • Test for race conditions on file access
  • Watch file activity with Procmon while using the app

Handy tools and commands:

# Weak permissions on the install folder (writable by low-priv users = risk)
icacls "C:\Program Files\App"
accesschk.exe -uwds "Users" "C:\Program Files\App" # -w writable, -s recurse

# Grep config and data files for secrets
findstr /s /i /n "password key token secret connectionstring" "C:\Program Files\App\*.config" "%APPDATA%\App\*"

# Verify the digital signature
Get-AuthenticodeSignature "C:\Program Files\App\app.exe"
sigcheck.exe -a -h app.exe

# Watch file access live (Procmon filter)
# Filter: Process Name is app.exe AND Operation is CreateFile / WriteFile
# Local database: open .db / .sqlite with DB Browser for SQLite

4. Registry Testing

  • Check read access to the app's registry keys
  • Check write access to the app's registry keys
  • Look for secrets or config stored in the registry
  • Diff the registry before and after running the app with Regshot
  • Try registry manipulation to bypass authentication
  • Try registry manipulation to bypass authorization or licensing
  • Check permissions on keys with AccessEnum

Handy tools and commands:

# Read the app's keys
reg query "HKCU\Software\App" /s
reg query "HKLM\SOFTWARE\App" /s

# Check write access to a key (accesschk, -k for registry)
accesschk.exe -k -w "Users" "HKLM\SOFTWARE\App"

# Diff before/after: Regshot -> 1st shot -> run app -> 2nd shot -> compare
# Watch live registry writes in Procmon (Operation is RegSetValue)

5. Network and Traffic Testing

  • Enumerate ports and services on the backend with Nmap
  • Capture traffic with Wireshark and look for cleartext data
  • Confirm whether traffic is encrypted (TLS) end to end
  • Test TLS strength with testssl.sh (versions, ciphers, certificate)
  • Intercept HTTP/S with Burp (use the NoPE extension if proxy-unaware)
  • Intercept non-HTTP traffic with Echo Mirage or MITM Relay
  • Test for certificate pinning and try to bypass it
  • Check whether the client accepts an invalid or self-signed server certificate
  • Check whether the client falls back to cleartext if TLS fails
  • Tamper with requests and responses and observe behavior
  • Test for injection and IDOR over the wire
  • Test WebSocket and gRPC traffic if used
  • Check live connections with TCPView

Handy tools and commands:

# Backend port and service scan
nmap -sV -sC -p- <host>

# TLS configuration and certificate check
testssl.sh <host>:443

# For a proxy-unaware client, force its traffic through Burp:
# - Proxifier or ProxyCap to redirect the process to 127.0.0.1:8080
# - Burp: Proxy > Options > enable invisible proxying, add the NoPE extension
# - Or edit the hosts file to point the backend domain at your proxy

# Non-HTTP TCP/TLS:
# Echo Mirage (inject into the process) or mitm_relay (relay to Burp)

# Cert pinning bypass at runtime with Frida:
frida -f app.exe -l frida-unpinning.js --no-pause

6. Binary and Assembly Protection Testing

  • Verify ASLR is enabled
  • Verify DEP is enabled
  • Verify SafeSEH
  • Verify Control Flow Guard (CFG)
  • Verify High Entropy VA
  • Verify strong naming (for .NET)
  • Verify Authenticode signing with Sigcheck

Handy tools and commands:

# Summarize all binary protections at once
winchecksec.exe app.exe
winchecksec.exe -j app.exe # JSON output for reports

# PowerShell alternative
Import-Module .\Get-PESecurity.psm1
Get-PESecurity -file "C:\Program Files\App\app.exe"

# Strong naming for .NET
sn.exe -vf app.exe

# Signature and hashes
sigcheck.exe -a -h app.exe

7. Memory Testing

  • Log in with known credentials and search memory for them
  • Search memory for passwords, keys, tokens, and PII
  • Confirm the region and protection of any hit with WinDbg !address
  • Check whether secrets are cleared after logout (search again)
  • Create a full memory dump and search it offline
  • Try memory manipulation to change values (for example an isAdmin flag)
  • Try to bypass authentication or authorization by editing memory
  • Set breakpoints on interesting functions with WinDbg or x64dbg
  • Hook and tamper with functions at runtime using Frida
  • Check for process replacement or hollowing indicators
  • Check crash dumps and Windows Error Reporting for leaked secrets
  • Check that the app disables memory paging for secrets (VirtualLock)

Handy tools and commands:

# Create a full memory dump
procdump.exe -ma <PID> out.dmp # Sysinternals ProcDump
# or Task Manager > Details > right-click process > Create dump file

# WinDbg: attach or open a dump
windbg -pn app.exe # attach to a live process by name
windbg -z out.dmp # open a dump

# WinDbg: search memory for a secret
s -u 0 L?7fffffff "Winter2024!" # Unicode search (most Windows text)
s -a 0 L?7fffffff "Winter2024!" # ASCII search
!address 000001f23a4b02c0 # confirm region + protection of a hit
du 000001f23a4b02c0 # read the hit as a Unicode string

# .NET managed heap (after loading SOS)
.loadby sos clr
!dumpheap -type System.String
!do <addr> # a String prints its text

# Frida: hook and read a function's arguments at runtime
frida -f app.exe -l hook.js --no-pause

8. Reverse Engineering and Code Testing

  • Decompile .NET assemblies with dnSpyEx, dotPeek, or ILSpy
  • Deobfuscate protected .NET assemblies with de4dot
  • Decompile Java or JAR files with JADX or JD-GUI
  • Disassemble native binaries with Ghidra, IDA, or Radare2
  • Recover source code, passwords, and keys
  • Identify exported functions and try to call them without authentication
  • Build a wrapper to call public methods without authentication
  • Patch and rebuild the app to bypass a check
  • Test for missing or weak obfuscation
  • Look for dangerous functions (strcpy, sprintf, system, exec)

Handy tools and commands:

# .NET: decompile and auto-deobfuscate
# dnSpyEx (GUI): open app.exe, browse code, edit, and save
de4dot.exe app.exe # writes app-cleaned.exe

# Java: decompile
jadx-gui app.jar # GUI decompiler
# or extract: jar xf app.jar

# Native: list exported functions of a DLL
dumpbin /exports app.dll # Visual Studio tools
# Ghidra / IDA / radare2 (r2 app.exe; aaa; pdf @ main) for disassembly

# Find dangerous native functions in the decompile
findstr /s /i "strcpy sprintf system exec WinExec ShellExecute" *.c *.cpp

9. Authentication and Authorization

  • Test for broken or weak authentication
  • Test for default or hardcoded credentials
  • Test whether auth checks are done on the client only
  • Bypass login using memory, registry, or binary patching
  • Test how the client stores and reuses session tokens (local storage, reuse, expiry)
  • Test for missing function-level access control enforced only on the client
  • Test privilege escalation paths (unlock admin features as a normal user)

Handy tools and commands:

# Client-side auth check bypass ideas:
# - dnSpyEx: find the method that returns the login/role result, edit it to
# always return true, then save the assembly and run.
# - x64dbg: set a breakpoint on the compare after the check, flip the ZF flag
# or NOP the conditional jump, then patch to file.
# - Memory: find an isAdmin / isLoggedIn flag and set it (WinDbg eb <addr> 01).

# Server-side authz (IDOR, function-level): capture the request in Burp and
# change identifiers or call admin-only endpoints as a normal user.

10. Data Storage and Secrets

  • Find hardcoded secrets in the binary or config
  • Check Windows Credential Manager and DPAPI usage
  • Check for secrets in logs
  • Check for secrets in environment variables
  • Check that sensitive data at rest is encrypted
  • Check backup, export, and temp files for leaked data

Handy tools and commands:

# Windows Credential Manager
cmdkey /list

# DPAPI-protected blobs (decrypt in the user's context)
# SharpDPAPI.exe or mimikatz "dpapi::*" during authorized testing

# Environment variables the app may read
Get-ChildItem Env:

# Grep common data folders for secrets
findstr /s /i "password key token secret" "%APPDATA%\App\*" "%PROGRAMDATA%\App\*" "%LOCALAPPDATA%\App\*"

11. Backend Communication and Injection

Focus on the inputs the thick client sends to its database or server. In a two-tier app the client talks directly to the database, so injection is a client-side concern. In a three-tier app, test the backend only through the client's own interfaces and traffic.

  • Test for SQL injection (direct client-to-database in two-tier, or via the backend)
  • Test for command injection through client inputs
  • Test for insecure deserialization (.NET BinaryFormatter, Java objects)
  • Test for XXE where the client or server parses XML
  • Test for IDOR and broken access control on backend resources the client calls
  • Test for business logic flaws in the client-to-server workflow

Handy tools and commands:

# SQL injection on the backend (proxy the request through Burp, save it, then)
sqlmap -r request.txt --batch

# Insecure deserialization gadget generation
ysoserial.net -f BinaryFormatter -g TypeConfuseDelegate -c "calc.exe" # .NET
java -jar ysoserial.jar CommonsCollections1 "calc.exe" > payload.bin # Java

# XXE: submit an XML body with an external entity and watch for file read / SSRF

12. DLL and Process Security

  • Test for DLL hijacking and search-order abuse
  • Test for DLL preloading and side-loading
  • Watch for missing DLLs with Procmon (NAME NOT FOUND filter)
  • Check permissions on the install directory (writable equals hijack risk)
  • Check for insecure service configuration and permissions
  • Check for insecure named pipes or IPC
  • Test for process injection weaknesses

Handy tools and commands:

# Find missing DLLs the app tries to load (classic hijack candidates)
# Procmon filter: Result is NAME NOT FOUND AND Path ends with .dll

# Is the install directory writable by normal users?
accesschk.exe -uwdq "Users" "C:\Program Files\App"

# Service misconfig (weak permissions, unquoted path)
sc qc <serviceName>
accesschk.exe -uwcqv "Users" <serviceName>
wmic service get name,pathname,startmode | findstr /i /v """ # unquoted paths

13. Cryptography

  • Identify the crypto algorithms and modes used
  • Check for weak or broken algorithms (MD5, DES, ECB)
  • Check for hardcoded keys or IVs
  • Break on crypto APIs to read keys at runtime (bcrypt, schannel)
  • Check for weak random number generation
  • Check that keys are stored and cleared safely

Handy tools and commands:

# In the decompiled code, search for weak primitives:
# MD5, SHA1, DES, RC4, ECB mode, hardcoded byte[] keys/IVs, Random() for keys

# Read keys at runtime by breaking on the crypto API (WinDbg):
bp bcrypt!BCryptDecrypt
bp bcrypt!BCryptGenerateSymmetricKey
g
db rdx L20 # inspect the key/IV/data buffer at the breakpoint

# Or trace all crypto calls with API Monitor (filter the Cryptography group)
# Or hook CryptoAPI / bcrypt functions with Frida and log key material

14. Logging and Error Handling

  • Check for verbose stack traces that leak information
  • Check for sensitive data written to logs
  • Check whether debug mode is left enabled
  • Check log file permissions
  • Test improper exception handling paths

Handy tools and commands:

# Find log files and scan them for secrets
Get-ChildItem -Recurse -Include *.log,*.txt "%APPDATA%\App","%PROGRAMDATA%\App","C:\Program Files\App"
findstr /s /i "password token exception stacktrace at " "%APPDATA%\App\*.log"

# Check log file permissions
icacls "%PROGRAMDATA%\App\logs"

# Trigger errors with malformed input and watch for detailed stack traces in the UI or logs

15. Software Update Mechanism

  • Identify how the app checks for and downloads updates
  • Check whether updates are fetched over HTTPS
  • Check whether update packages have a verified digital signature
  • Try to serve a malicious update through a man-in-the-middle position
  • Check whether the update process runs with elevated privileges (update-to-EoP)
  • Check the update download folder permissions (writable equals binary planting)
  • Check for downgrade or rollback to a vulnerable version

Handy tools and commands:

# Watch the update check in Burp or Wireshark: is it HTTP or HTTPS?
# MITM the update endpoint (hosts file or proxy) and return a modified installer.
# If the client runs the file without verifying its signature, that is RCE.

# Verify whether the downloaded update is signature-checked:
sigcheck.exe -a downloaded_update.exe # is it signed, and does the app enforce it?

# Check the download/staging folder permissions
accesschk.exe -uwdq "Users" "%LOCALAPPDATA%\App\Update"

16. Inter-Process Communication (IPC)

  • Enumerate named pipes and check their permissions and authentication
  • Test COM and DCOM objects for insecure access and privilege abuse
  • Test RPC and local RPC endpoints
  • Test WCF or .NET remoting endpoints if used
  • Check shared memory and memory-mapped files for exposed data
  • Test window messages (WM_COPYDATA) and mailslots
  • Check whether IPC endpoints validate the caller and its integrity level

Handy tools and commands:

# List named pipes
pipelist.exe # Sysinternals
[System.IO.Directory]::GetFiles("\\.\pipe\") # PowerShell one-liner

# Check a pipe's permissions
accesschk.exe -w \pipe\<pipeName>

# COM / DCOM inspection
# OleViewDotNet (GUI) to browse COM classes, interfaces, and access permissions
# RpcView (GUI) to enumerate RPC interfaces and endpoints

17. Privilege Escalation and Persistence

  • Check for unquoted service paths
  • Check service binary and folder permissions (writable equals code execution as the service account)
  • Check service configuration change rights with accesschk
  • Check scheduled tasks created by the app for weak permissions
  • Test the installer and updater for writing to weakly protected locations
  • Check for UAC bypass or silent auto-elevation
  • Check autostart entries (Run keys, startup folder) for write access
  • Check whether the app runs as SYSTEM or admin unnecessarily

Handy tools and commands:

# Automated privilege-escalation checks
.\winPEASx64.exe # winPEAS
powershell -ep bypass -c "Import-Module .\PowerUp.ps1; Invoke-AllChecks"

# Unquoted service paths
wmic service get name,displayname,pathname,startmode | findstr /i /v "c:\windows\\" | findstr /i /v """

# Service permission and config
sc qc <serviceName>
accesschk.exe -uwcqv "Users" <serviceName>

# Scheduled tasks and autostart
schtasks /query /fo LIST /v
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"

18. Protocol Handlers and Argument Injection

  • Enumerate custom URL or protocol handlers the app registers (for example myapp://)
  • Test protocol handler input for argument and command injection
  • Test command-line arguments for injection and unsafe behavior
  • Test file association handlers with crafted files
  • Test deep links that trigger sensitive actions without confirmation

Handy tools and commands:

# Find custom protocol handlers registered under HKCR
reg query "HKCR" | findstr /i "URL Protocol"
reg query "HKCR\myapp\shell\open\command"

# Trigger a handler with a crafted argument
start "" "myapp://open?file=..\..\sensitive"

# Test how the app parses its command line (look for injection into a shell/path)
app.exe --config "test&calc.exe"

19. Framework-Specific Tests

Electron:

  • Extract and inspect the ASAR archive (app.asar) for source and secrets
  • Check nodeIntegration and contextIsolation settings
  • Check for remote content loaded into privileged windows (XSS to RCE)
  • Check the Electron and Chromium version for known CVEs

Java:

  • Test RMI and JMX endpoints
  • Test for insecure deserialization of Java objects
  • Decompile JAR or class files and look for secrets and logic

.NET:

  • Inspect config files (app.config) for connection strings and settings
  • Check for insecure BinaryFormatter or SOAP deserialization
  • Check ClickOnce deployment and manifest trust settings

Handy tools and commands:

# Electron: extract and read the app source
npx asar extract app.asar out
electronegativity -i out # scan for insecure Electron settings

# Java: deserialization payload
java -jar ysoserial.jar CommonsCollections1 "calc.exe" > payload.bin

# .NET: deserialization payload
ysoserial.net -f BinaryFormatter -g TypeConfuseDelegate -c "calc.exe"

20. Local and Embedded Servers

  • Check whether the app opens a listener on localhost or a broader interface
  • Test any local web or API server for authentication and CSRF
  • Check for sensitive actions reachable from the browser or other local apps
  • Check the bound interface (localhost only vs 0.0.0.0)

Handy tools and commands:

# What is the app listening on, and on which interface?
netstat -ano | findstr LISTENING | findstr <PID>

# Probe the local endpoint
curl http://127.0.0.1:<port>/ -v

# If it is 0.0.0.0, it is reachable from the network, not just localhost.
# Test the endpoint for missing auth and CSRF (a web page can call localhost).

21. Licensing and Business Logic

  • Test client-side license, trial, or activation checks for bypass
  • Test feature flags and paywalls enforced only on the client
  • Test for hidden or debug menus and backdoor functionality
  • Check clipboard for sensitive data left after copy operations
  • Test workflow and state manipulation for logic flaws

Handy tools and commands:

# License/trial bypass ideas:
# - dnSpyEx / x64dbg: find the IsLicensed / IsTrialExpired check and patch it.
# - Registry/file: locate the trial timestamp and reset or delete it (Procmon
# and Regshot help find where it is stored).
# - Feature flags stored client-side: flip them in config, registry, or memory.

# Clipboard leakage: after a copy action, inspect the clipboard
powershell -c "Get-Clipboard"

22. Reporting

  • Record clear reproduction steps for every finding
  • Capture evidence (screenshots, dumps, tool output)
  • Rate severity and impact
  • Provide remediation guidance for each finding
  • Note the environment, versions, and scope tested

Handy tips:

# Save tool output as evidence alongside screenshots:
winchecksec.exe -j app.exe > evidence\binary-protections.json
sigcheck.exe -a app.exe > evidence\signature.txt
# Keep the memory dump (out.dmp) and the exact WinDbg search command used.
# Record app version, build, OS version, and the account privilege level tested.