Skip to main content

HTB-Partial_Encryption

Table of Contents

Difficulty: Easy
OS: Windows
Date: 2026-01-26
Description:
Static-Analysis on this program didn’t reveal much. There must be a better way to approach this…

Static Analysis
#

Отриманий файл - PE execiteble для Windows 64-bit

1$ file *                                                        
2partialencryption.exe: PE32+ executable for MS Windows 6.00 (console), x86-64, 5 sections

Packer
#

Містить невелику кількість imports, що вказують на пакуваня (VirtualAlloc VirtualProtect VirtualFree) та на anti-dynamic analysis:
- IsDebuggerPresent - перевірка чи програма працює під дебагером - QueryPerformanceCounter та GetSystemTimeAsFileTime - можуть використовутися для вимирювання часу між інструкціями

 1VirtualAlloc
 2VirtualProtect
 3VirtualFree
 4QueryPerformanceCounter
 5GetCurrentProcessId
 6GetCurrentThreadId
 7GetSystemTimeAsFileTime
 8InitializeSListHead
 9RtlCaptureContext
10RtlLookupFunctionEntry
11RtlVirtualUnwind
12IsDebuggerPresent
13UnhandledExceptionFilter
14SetUnhandledExceptionFilter
15IsProcessorFeaturePresent
16GetModuleHandleW
17KERNEL32.dll

Reversing
#

by static analysis i found that used aeskeygenassist та aesdeclast instructions. Це вказує на використання процесорних розширень Intel AES-NI для криптографічних операцій - aeskeygenassist used to assist in generating round keys on-the-fly

  • aesdeclast performs the final round of the decryption state
    alt text

Dynamic Analysis
#

just running
#

i tried run program

C:\Users\f\Desktop>partialencryption.exe aaaaaaaa
Nope

C:\Users\f\Desktop>partialencryption.exe aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
No

Running over x64dbg
#

I placed a breakpoint on the VirtualAlloc call to identify where data is being written in memory. I set a hardware breakpoint on that address, resumed execution, but only received a Nope message. This indicated that a check was failing before the program jumped to the decrypted data.

alt text

I then executed the program with a longer input string (e.g., aaa...) to observe its behavior under those conditions.

alt text

In this case, the program began checking individual characters of the flag.

 1...[snip]...
 2| mov rax,qword ptr ds:[rdx+rax]          |
 3| movsx eax,byte ptr ds:[rax+rcx]         |
 4| cmp eax,48                              | 48:'H'
 5...[snip]...
 6| mov rax,qword ptr ds:[rdx+rax]          |
 7| movsx eax,byte ptr ds:[rax+rcx]         |
 8| cmp eax,54                              | 54:'T'
 9...[snip]...
10| mov rax,qword ptr ds:[rdx+rax]          |
11| movsx eax,byte ptr ds:[rax+rcx]         |
12| cmp eax,42                              | 42:'B'
13...[snip]...
14| mov rax,qword ptr ds:[rdx+rax]          |
15| movsx eax,byte ptr ds:[rax+rcx]         |
16| cmp eax,7B                              | 7B:'{'
17...[snip]...
18| imul rcx,rcx,15                         | rcx:putchar
19| mov rdx,qword ptr ss:[rsp+48]           | rdx:exit
20| mov rax,qword ptr ds:[rdx+rax]          |
21| movsx eax,byte ptr ds:[rax+rcx]         |
22| cmp eax,7D                              | 7D:'}}'
23...[snip]...

Continuing debugging, I found three identical blocks of code that handle decryption and execution:

 1| mov r8d,8000                            |
 2| xor edx,edx                             |
 3| mov rcx,qword ptr ss:[rsp+30]           |
 4| call qword ptr ds:[<VirtualFree>]       |
 5| xor eax,eax                             |
 6| cmp eax,1                               |
 7| je partialencryption.7FF62E0F149A       |
 8| mov edx,1E0                             |  ## size 480 bytes
 9| lea rcx,qword ptr ds:[7FF62E0F42E0]     |  ## encryption data source
10| call partialencryption.7FF62E0F1050     |  ## decrypting payload into memory
11...[snip]...
12| call qword ptr ss:[rsp+58]              |  ## jumps directly to the start of that new decrypted code

By placing breakpoints on these dynamic call qword ptr ss:[rsp+??] instructions, we intercepted the decrypted logic for each stage.

call qword ptr ss:[rsp+58]:

 1...[snip]...
 2| mov rax,qword ptr ds:[rdx+rax]          |
 3| movsx eax,byte ptr ds:[rax+rcx]         |
 4| cmp eax,57                              | 57:'W'
 5...[snip]...
 6| cmp eax,33                              | 33:'3'
 7...[snip]...
 8| cmp eax,33                              | 33:'3'
 9...[snip]...
10| cmp eax,52                              | 52:'R'
11...[snip]...
12| cmp eax,52                              | 52:'R'
13...[snip]...
14| cmp eax,5F                              | 5F:'_'

By debugging the remaining two parts, I obtained the final flag: HTB{W3iRd_RUnT1m3_DEC}.