Home Hackvent 2015 Dec 16: Reversing #2
Writeup
Cancel

Dec 16: Reversing #2

Challenge

xmas encryptor

todays code was encrypted by our mighty xmas encryptor. you are given the executable and the encrypted key. can you find a vulnerability in our code to decrypt the daily code?

file

Hint: do not ignore constants in the encrypt() routine - it can help you to identify the algorithm.

Solution

This was a tough one for me. We got a windows executable, and a file with the encrypted nugget.

We disassemble the file:

link

CODE:00401000 ;
CODE:00401000 ; +-------------------------------------------------------------------------+
CODE:00401000 ; |   This file has been generated by The Interactive Disassembler (IDA)    |
CODE:00401000 ; |           Copyright (c) 2015 Hex-Rays, <support@hex-rays.com>           |
CODE:00401000 ; |                           Evaluation version                            |
CODE:00401000 ; +-------------------------------------------------------------------------+
CODE:00401000 ;
CODE:00401000 ; Input MD5   : C8898E2B195C4ED57EBAD43B9320F2E5
CODE:00401000 ; Input CRC32 : 81B7419B
CODE:00401000
CODE:00401000 ; File Name   : E:\personal\CTF\ctf-writeups\CTF-writeups-private\Hackvent_2015\writeupfiles\HVenc\hackvent_encryptor.exe
CODE:00401000 ; Format      : Portable executable for 80386 (PE)
CODE:00401000 ; Imagebase   : 400000
CODE:00401000 ; Section 1. (virtual address 00001000)
CODE:00401000 ; Virtual size                  : 00001000 (   4096.)
CODE:00401000 ; Section size in file          : 00000200 (    512.)
CODE:00401000 ; Offset to raw data for section: 00000600
CODE:00401000 ; Flags 60000020: Text Executable Readable
CODE:00401000 ; Alignment     : default
CODE:00401000
CODE:00401000                 .686p
CODE:00401000                 .mmx
CODE:00401000                 .model flat
CODE:00401000
CODE:00401000 ; ===========================================================================
CODE:00401000
CODE:00401000 ; Segment type: Pure code
CODE:00401000 ; Segment permissions: Read/Execute
CODE:00401000 CODE            segment para public 'CODE' use32
CODE:00401000                 assume cs:CODE
CODE:00401000                 ;org 401000h
CODE:00401000                 assume es:nothing, ss:nothing, ds:CODE, fs:nothing, gs:nothing
CODE:00401000
CODE:00401000 ; =============== S U B R O U T I N E =======================================
CODE:00401000
CODE:00401000 ; Attributes: bp-based frame
CODE:00401000
CODE:00401000 sub_401000      proc near               ; CODE XREF: start+87p
CODE:00401000
CODE:00401000 arg_0           = dword ptr  8
CODE:00401000 arg_4           = dword ptr  0Ch
CODE:00401000
CODE:00401000                 enter   0, 0
CODE:00401004                 pusha
CODE:00401005                 mov     esi, [ebp+arg_4]
CODE:00401008                 mov     eax, [esi]
CODE:0040100A                 mov     ebx, [esi+4]
CODE:0040100D                 mov     ecx, [esi+8]
CODE:00401010                 mov     edx, [esi+0Ch]
CODE:00401013                 mov     ds:dword_40203C, eax
CODE:00401018                 mov     ds:dword_402040, ebx
CODE:0040101E                 mov     ds:dword_402044, ecx
CODE:00401024                 mov     ds:dword_402048, edx
CODE:0040102A                 push    ebp
CODE:0040102B                 mov     ebx, [ebp+arg_0]
CODE:0040102E                 xor     edx, edx
CODE:00401030                 mov     esi, [ebx]
CODE:00401032                 mov     edi, [ebx+4]
CODE:00401035                 mov     ebp, 20h
CODE:0040103A
CODE:0040103A loc_40103A:                             ; CODE XREF: sub_401000+81j
CODE:0040103A                 add     edx, 9E3779B9h
CODE:00401040                 mov     eax, edi
CODE:00401042                 mov     ecx, eax
CODE:00401044                 mov     ebx, edi
CODE:00401046                 shl     eax, 4
CODE:00401049                 shr     ebx, 5
CODE:0040104C                 add     eax, ds:dword_40203C
CODE:00401052                 add     ebx, ds:dword_402040
CODE:00401058                 add     ecx, edx
CODE:0040105A                 xor     ecx, eax
CODE:0040105C                 xor     ecx, ebx
CODE:0040105E                 add     esi, ecx
CODE:00401060                 mov     eax, esi
CODE:00401062                 mov     ebx, esi
CODE:00401064                 mov     ecx, esi
CODE:00401066                 shl     eax, 4
CODE:00401069                 shr     ebx, 5
CODE:0040106C                 add     eax, ds:dword_402044
CODE:00401072                 add     ebx, ds:dword_402048
CODE:00401078                 add     ecx, edx
CODE:0040107A                 xor     ecx, eax
CODE:0040107C                 xor     ecx, ebx
CODE:0040107E                 add     edi, ecx
CODE:00401080                 dec     ebp
CODE:00401081                 jnz     short loc_40103A
CODE:00401083                 mov     ds:dword_40203C, ebp
CODE:00401089                 mov     ds:dword_402040, ebp
CODE:0040108F                 mov     ds:dword_402044, ebp
CODE:00401095                 mov     ds:dword_402048, ebp
CODE:0040109B                 pop     ebp
CODE:0040109C                 mov     ebx, [ebp+arg_0]
CODE:0040109F                 mov     [ebx], esi
CODE:004010A1                 mov     [ebx+4], edi
CODE:004010A4                 popa
CODE:004010A5                 leave
CODE:004010A6                 retn    8
CODE:004010A6 sub_401000      endp
CODE:004010A6
CODE:004010A9
CODE:004010A9 ; =============== S U B R O U T I N E =======================================
CODE:004010A9
CODE:004010A9 ; Attributes: noreturn
CODE:004010A9
CODE:004010A9                 public start
CODE:004010A9 start           proc near
CODE:004010A9                 push    0               ; lpModuleName
CODE:004010AB                 call    GetModuleHandleA
CODE:004010B0                 call    GetCurrentProcessId
CODE:004010B5                 imul    eax, 12345678h
CODE:004010BB                 mov     ds:dword_402074, eax
CODE:004010C0                 xor     eax, 0BABEF00Dh
CODE:004010C5                 mov     ds:dword_402078, eax
CODE:004010CA                 sub     eax, 1EE7C0DEh
CODE:004010CF                 mov     ds:dword_40207C, eax
CODE:004010D4                 add     eax, 42424242h
CODE:004010D9                 mov     ds:dword_402080, eax
CODE:004010DE                 push    0               ; hTemplateFile
CODE:004010E0                 push    0               ; dwFlagsAndAttributes
CODE:004010E2                 push    3               ; dwCreationDisposition
CODE:004010E4                 push    0               ; lpSecurityAttributes
CODE:004010E6                 push    3               ; dwShareMode
CODE:004010E8                 push    0C0000000h      ; dwDesiredAccess
CODE:004010ED                 push    offset FileName ; "key.txt"
CODE:004010F2                 call    CreateFileA
CODE:004010F7                 mov     ds:hFile, eax
CODE:004010FC                 cmp     ds:hFile, 0FFFFFFFFh
CODE:00401103                 jz      short loc_401165
CODE:00401105                 push    0               ; lpOverlapped
CODE:00401107                 push    offset NumberOfBytesWritten ; lpNumberOfBytesRead
CODE:0040110C                 push    20h             ; nNumberOfBytesToRead
CODE:0040110E                 push    offset unk_402050 ; lpBuffer
CODE:00401113                 push    ds:hFile        ; hFile
CODE:00401119                 call    ReadFile
CODE:0040111E                 xor     ecx, ecx
CODE:00401120                 mov     esi, offset unk_402050
CODE:00401125
CODE:00401125 loc_401125:                             ; CODE XREF: start+90j
CODE:00401125                 cmp     ecx, 4
CODE:00401128                 jz      short loc_40113B
CODE:0040112A                 push    offset dword_402074
CODE:0040112F                 push    esi
CODE:00401130                 call    sub_401000
CODE:00401135                 add     esi, 8
CODE:00401138                 inc     ecx
CODE:00401139                 jmp     short loc_401125
CODE:0040113B ; ---------------------------------------------------------------------------
CODE:0040113B
CODE:0040113B loc_40113B:                             ; CODE XREF: start+7Fj
CODE:0040113B                 push    0               ; dwMoveMethod
CODE:0040113D                 push    0               ; lpDistanceToMoveHigh
CODE:0040113F                 push    0               ; lDistanceToMove
CODE:00401141                 push    ds:hFile        ; hFile
CODE:00401147                 call    SetFilePointer
CODE:0040114C                 push    0               ; lpOverlapped
CODE:0040114E                 push    offset NumberOfBytesWritten ; lpNumberOfBytesWritten
CODE:00401153                 push    20h             ; nNumberOfBytesToWrite
CODE:00401155                 push    offset unk_402050 ; lpBuffer
CODE:0040115A                 push    ds:hFile        ; hFile
CODE:00401160                 call    WriteFile
CODE:00401165
CODE:00401165 loc_401165:                             ; CODE XREF: start+5Aj
CODE:00401165                 push    ds:hFile        ; hObject
CODE:0040116B                 call    CloseHandle
CODE:00401170                 push    40h             ; uType
CODE:00401172                 push    offset Caption  ; "Hackvent 2015"
CODE:00401177                 push    offset Text     ; "file key.txt successfully encrypted!"
CODE:0040117C                 push    0               ; hWnd
CODE:0040117E                 call    MessageBoxA
CODE:00401183                 push    0               ; uExitCode
CODE:00401185                 call    ExitProcess
CODE:00401185 start           endp
CODE:00401185
CODE:0040118A ; [00000006 BYTES: COLLAPSED FUNCTION CloseHandle. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:00401190 ; [00000006 BYTES: COLLAPSED FUNCTION ExitProcess. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:00401196 ; [00000006 BYTES: COLLAPSED FUNCTION CreateFileA. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:0040119C ; [00000006 BYTES: COLLAPSED FUNCTION GetModuleHandleA. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011A2 ; [00000006 BYTES: COLLAPSED FUNCTION ReadFile. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011A8 ; [00000006 BYTES: COLLAPSED FUNCTION SetFilePointer. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011AE ; [00000006 BYTES: COLLAPSED FUNCTION WriteFile. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011B4 ; [00000006 BYTES: COLLAPSED FUNCTION GetCurrentProcessId. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011BA ; [00000006 BYTES: COLLAPSED FUNCTION MessageBoxA. PRESS CTRL-NUMPAD+ TO EXPAND]
CODE:004011C0                 align 80h
CODE:00401200                 dd 380h dup(?)
CODE:00401200 CODE            ends
CODE:00401200
DATA:00402000 ; Section 2. (virtual address 00002000)
DATA:00402000 ; Virtual size                  : 00001000 (   4096.)
DATA:00402000 ; Section size in file          : 00000200 (    512.)
DATA:00402000 ; Offset to raw data for section: 00000800
DATA:00402000 ; Flags C0000040: Data Readable Writable
DATA:00402000 ; Alignment     : default
DATA:00402000 ; ===========================================================================
DATA:00402000
DATA:00402000 ; Segment type: Pure data
DATA:00402000 ; Segment permissions: Read/Write
DATA:00402000 DATA            segment para public 'DATA' use32
DATA:00402000                 assume cs:DATA
DATA:00402000                 ;org 402000h
DATA:00402000 ; CHAR FileName[]
DATA:00402000 FileName        db 'key.txt',0          ; DATA XREF: start+44o
DATA:00402008 ; CHAR Caption[]
DATA:00402008 Caption         db 'Hackvent 2015',0    ; DATA XREF: start+C9o
DATA:00402016 ; CHAR Text[]
DATA:00402016 Text            db 'file key.txt successfully encrypted!',0
DATA:00402016                                         ; DATA XREF: start+CEo
DATA:0040203B                 align 4
DATA:0040203C dword_40203C    dd 0                    ; DATA XREF: sub_401000+13w
DATA:0040203C                                         ; sub_401000+4Cr ...
DATA:00402040 dword_402040    dd 0                    ; DATA XREF: sub_401000+18w
DATA:00402040                                         ; sub_401000+52r ...
DATA:00402044 dword_402044    dd 0                    ; DATA XREF: sub_401000+1Ew
DATA:00402044                                         ; sub_401000+6Cr ...
DATA:00402048 dword_402048    dd 0                    ; DATA XREF: sub_401000+24w
DATA:00402048                                         ; sub_401000+72r ...
DATA:0040204C ; HANDLE hFile
DATA:0040204C hFile           dd 0                    ; DATA XREF: start+4Ew
DATA:0040204C                                         ; start+53r ...
DATA:00402050 unk_402050      db    0                 ; DATA XREF: start+65o
DATA:00402050                                         ; start+77o ...
DATA:00402051                 db    0
DATA:00402052                 db    0
DATA:00402053                 db    0
DATA:00402054                 db    0
DATA:00402055                 db    0
DATA:00402056                 db    0
DATA:00402057                 db    0
DATA:00402058                 db    0
DATA:00402059                 db    0
DATA:0040205A                 db    0
DATA:0040205B                 db    0
DATA:0040205C                 db    0
DATA:0040205D                 db    0
DATA:0040205E                 db    0
DATA:0040205F                 db    0
DATA:00402060                 db    0
DATA:00402061                 db    0
DATA:00402062                 db    0
DATA:00402063                 db    0
DATA:00402064                 db    0
DATA:00402065                 db    0
DATA:00402066                 db    0
DATA:00402067                 db    0
DATA:00402068                 db    0
DATA:00402069                 db    0
DATA:0040206A                 db    0
DATA:0040206B                 db    0
DATA:0040206C                 db    0
DATA:0040206D                 db    0
DATA:0040206E                 db    0
DATA:0040206F                 db    0
DATA:00402070 ; DWORD NumberOfBytesWritten
DATA:00402070 NumberOfBytesWritten dd 0               ; DATA XREF: start+5Eo
DATA:00402070                                         ; start+A5o
DATA:00402074 dword_402074    dd 0                    ; DATA XREF: start+12w
DATA:00402074                                         ; start+81o
DATA:00402078 dword_402078    dd 0                    ; DATA XREF: start+1Cw
DATA:0040207C dword_40207C    dd 0                    ; DATA XREF: start+26w
DATA:00402080 dword_402080    dd 0                    ; DATA XREF: start+30w
DATA:00402084                 align 1000h
DATA:00402084 DATA            ends
DATA:00402084
.idata:00403000 ; Section 3. (virtual address 00003000)
.idata:00403000 ; Virtual size                  : 00001000 (   4096.)
.idata:00403000 ; Section size in file          : 00000200 (    512.)
.idata:00403000 ; Offset to raw data for section: 00000A00
.idata:00403000 ; Flags C0000040: Data Readable Writable
.idata:00403000 ; Alignment     : default
.idata:00403000 ; ===========================================================================
.idata:00403000
.idata:00403000 ; Segment type: Externs
.idata:00403000 ; _idata
.idata:00403000
.idata:00403001
.idata:00403068 ;
.idata:00403068 ; Imports from KERNEL32.dll
.idata:00403068 ;
.idata:00403068 ; BOOL __stdcall CloseHandle(HANDLE hObject)
.idata:00403068                 extrn __imp_CloseHandle:dword ; DATA XREF: CloseHandler
.idata:0040306C ; void __stdcall __noreturn ExitProcess(UINT uExitCode)
.idata:0040306C                 extrn __imp_ExitProcess:dword ; DATA XREF: ExitProcessr
.idata:00403070 ; HANDLE __stdcall CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
.idata:00403070                 extrn __imp_CreateFileA:dword ; DATA XREF: CreateFileAr
.idata:00403074 ; HMODULE __stdcall GetModuleHandleA(LPCSTR lpModuleName)
.idata:00403074                 extrn __imp_GetModuleHandleA:dword
.idata:00403074                                         ; DATA XREF: GetModuleHandleAr
.idata:00403078 ; BOOL __stdcall ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
.idata:00403078                 extrn __imp_ReadFile:dword ; DATA XREF: ReadFiler
.idata:0040307C ; DWORD __stdcall SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
.idata:0040307C                 extrn __imp_SetFilePointer:dword
.idata:0040307C                                         ; DATA XREF: SetFilePointerr
.idata:00403080 ; BOOL __stdcall WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
.idata:00403080                 extrn __imp_WriteFile:dword ; DATA XREF: WriteFiler
.idata:00403084 ; DWORD __stdcall GetCurrentProcessId()
.idata:00403084                 extrn __imp_GetCurrentProcessId:dword
.idata:00403084                                         ; DATA XREF: GetCurrentProcessIdr
.idata:00403088
.idata:0040308C ;
.idata:0040308C ; Imports from USER32.dll
.idata:0040308C ;
.idata:0040308C ; int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
.idata:0040308C                 extrn __imp_MessageBoxA:dword ; DATA XREF: MessageBoxAr
.idata:00403090
.idata:00403090
.idata:00403090
.idata:00403090                 end start

We see that the key is constructed using the current processId as a seed:

CODE:004010AB                 call    GetModuleHandleA
CODE:004010B0                 call    GetCurrentProcessId
CODE:004010B5                 imul    eax, 12345678h
CODE:004010BB                 mov     ds:dword_402074, eax
CODE:004010C0                 xor     eax, 0BABEF00Dh
CODE:004010C5                 mov     ds:dword_402078, eax
CODE:004010CA                 sub     eax, 1EE7C0DEh
CODE:004010CF                 mov     ds:dword_40207C, eax
CODE:004010D4                 add     eax, 42424242h
CODE:004010D9                 mov     ds:dword_402080, eax

This must be the vulnerability the challenge text alluded to, as the process Id in practice never gets very high. So if we can reverse the encryption, we could just try a number of different keys until it decrypts to something starting with HV15.

The decryption proved difficult to perform. After the hint was released, we finally got on the right track. Turns out googling the constant used at the beginning of the encryption function would lead you to the algorithm:

CODE:0040103A loc_40103A:                             ; CODE XREF: sub_401000+81j
CODE:0040103A                 add     edx, 9E3779B9h

Turns out this is Tiny Encryption Algorithm (TEA).

Flag