Nytro Posted November 22, 2014 Report Posted November 22, 2014 (edited) assembly, c-sharp, anti-sandbox, anti-antivirus, anti-debug, and malware researchHello fellow readers! You all are probably wondering what the hell I’ve been up to this past month. Lot’s of stuff. This post is all over the place with code and slides and malware and general wackiness. Rather than spreading it out over several blog posts, I decided to just get it all over with so I can focus on cooler things in the future. I saw an interesting webinar on sandbox detection techniques employed by malware by Cyphort. They haven’t released their slides like they said they would, so here are the ones I took. These are cool and all, but I felt like I could contribute. I read an awesome paper on bypassing antiviruses by employing a number of code based tricks. The idea behind them was that AV’s will skip binaries based on certain behaviors. One thing missing though – an AV will skip the “dropper” heuristic if the file ends in ‘.msi’. All the code I saw was in C/C++. I figured why not try and convert it to assembly? Next thing to do is make a patcher that can inject these into pre-compiled binaries. A future project perhaps? Anyways, I only did 2 before I lost interest. Read the article here. ;AV bypass 1xor eax, eaxdb Caption "Joe"db Text "Giron"mov edx, 5F5E100hjoe:inc eaxdec edxjnz joecmp eax, 5F5E100hjnz short urafagpush 0 ; MB_OKpush offset Captionpush offset Text push 0 ; hWnd call MessageBoxAurafag:xor eax, eaxretn;AV bypass 1.5; same as above, just using the loop instruction instead of branching conditionalsxor eax, eaxdb Caption "Joe"db Text "Giron"mov ecx, 5F5E100hjoe: ; essentially do nothingmov eax,10mov ebx,20xchg eax,ebxloop joe; now start codexor eax,eaxxor ebx,ebxpush 0 ; MB_OKpush offset Captionpush offset Text push 0 ; hWnd call MessageBoxAretn;AV bypass 2push ebxpush edipush 5F5E100h ; bytes to allocpush 40h ; zero initcall GlobalAllocmov ebx, eaxtest ebx, ebxjz short cleanupmov edi, ebxmov eax, 0FFFFFFF1hmov ecx, 5F5E100hrep stosbpush 0 ; MB_OKpush offset Caption ; "Joe"push offset Text ; "Giron"push 0 ; hWndcall MessageBoxApush ebx ; memory handlercall GlobalFreecleanup: xor eax, eaxpop edipop ebxretn Feels good to put my crappy assembly skills to good use. Especially now that I figured out how to use inline assembly within C#. Sort of. The way it works is by utilizing delegates and cramming code inside an executable code page. Observe this piece of genius: using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace InLineAsm{ static class Program { [unmanagedFunctionPointer(CallingConvention.StdCall )] delegate void JoesAntiDebuggery(); [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, IntPtr flAllocationType, IntPtr flProtect); static byte[] opcodez = { 0x55, 0x89, 0xE5, 0x31, 0xC0, 0xBA, 0x00, 0xE1, 0xF5, 0x05, 0x40, 0x4A, 0x75, 0xFC, 0x3D, 0x00, 0xE1, 0xF5, 0x05, 0x75, 0x14, 0x6A, 0x00, 0x68, 0x12 ,0x70, 0x40, 0x00, 0x68, 0x0C, 0x70, 0x40, 0x00, 0x6A, 0x00, 0xFF, 0x15, 0xD0, 0x80, 0x40, 0x00, 0x31, 0xC0, 0x68, 0x00, 0x70, 0x40, 0x00, 0xE8, 0x3B, 0x00, 0x00, 0x00, 0x59, 0x31, 0xC0, 0x89, 0xEC, 0x5D, 0xC3 } // opcodes taken from disassembled program. /* __asm { xor eax, eax mov edx, 5F5E100h joe: inc eax dec edx jnz joe cmp eax, 5F5E100h jnz short urafag } MessageBox(0,Text, Caption,0); __asm { urafag: xor eax, eax } */ static IntPtr codeBuffer = VirtualAlloc(IntPtr.Zero, new UIntPtr((uint)opcodez.Length), (IntPtr)(0x1000 | 0x2000), (IntPtr)0x40); // EXECUTE_READWRITE, MEM_COMMIT | MEM_RESERVE Marshal.Copy(opcodez, 0,codeBuffer, opcodez.Length); JoesAntiDebuggery JoeDbg = (JoesAntiDebuggery) Marshal.GetDelegateForFunctionPointer(codeBuffer, typeof(JoesAntiDebuggery)); static void Main(string[] args) { Console.Write("lol"); JoeDbg(); } }} It’s a thing of beauty – Assembly, C code, op codes / hex, delegates, and C#. Moving on to what else I’ve been up to – pulling apart malwarez. This one piece gave me trouble for a few days. Namely because of the weird anti-debugging counter measure I encountered. I’m unsure if its even anti-debug as the conditions always seem to equate to false. I mean it’s easy to get around when you see it, but you can’t get around it automatically – you have to patch it. I even took a video of the weird behavior. Took me some time, but I figured it out. The following is the sequence called not 5 instructions after the entry point sub_4017CF proc near push ebpmov edi, edxadd edi, ebxnot ebxmov ebp, espadd edi, ebxadd esp, 0FFFFFF94hmov edx, ebxinc ebxmov ecx, espdec ebxmov edi, eaxadd ecx, 48hmov ebx, ecxdec edicmp eax, ecxjz short labelforyouneg edxleavenot edxmov eax, edineg eaxleaveadd edx, edinot edxretnlabelforyou: leaveretn The first thing you may notice about this procedure is the weird stack frame setup. Most of the time, the intro stack frame will be “push ebp” followed directly by “mov ebp, esp”. This one is different in that it plays with the registers a little before the “mov ebp, esp” assembly codes. You may also notice the 2 “leave” instructions at the end of the procedure as opposed to the 1 for the “labelforyou” conditional. The 2 “leave” instructions are why the program jumps to ExitThread. When you leave a stack frame twice and ‘ret’, any windows program jumps to ntdll.RtlExitUserThread. An interesting intrinsic way of quietly exiting without warning. But what about the code that leads up to the ‘JZ’ branch and the 2 leaves? The comparison is EAX to ECX. Every time I run, EAX always ends up as 1 and ECX as some stack address. I’m postulating that the malware I grabbed was extracted from a dropper. That makes sense given the stack value / pointer points to nothing useful. If you’re curious what the malware does, it attempts to download and run a ‘doc’ file from a russian host. Inside the ‘doc’ file is HTML code with a meta redirect to a host my DNS server can’t seem to find:You can download the malware here. Pass in ‘infected’. The other piece of malware I went through lacked a DOS sub. Most exe’s have this little DOS application inside that reads “this program cannot be run in DOS mode” and is placed at the start of an exe just in case someone attempts to run an exe on an old DOS system. Its a forward compatibility thing Microsoft does. Compare a normal exe to the binary: So how the hell do you remove the DOS sub and still maintain functionality? According to TinyPE, you do it in assembly via zeroing out the MZ header with the exception of the ‘e_magic’ field ‘MZ’ at the start and the ‘e_lfanew’ field value at the bottom. The ‘e_lfanew’ field is just a 4 byte offset to where the PE header is located. mzhdr: dw "MZ" ; e_magic dw 0 ; e_cblp UNUSED dw 0 ; e_cp UNUSED dw 0 ; e_crlc UNUSED dw 0 ; e_cparhdr UNUSED dw 0 ; e_minalloc UNUSED dw 0 ; e_maxalloc UNUSED dw 0 ; e_ss UNUSED dw 0 ; e_sp UNUSED dw 0 ; e_csum UNUSED dw 0 ; e_ip UNUSED dw 0 ; e_cs UNUSED dw 0 ; e_lsarlc UNUSED dw 0 ; e_ovno UNUSED times 4 dw 0 ; e_res UNUSED dw 0 ; e_oemid UNUSED dw 0 ; e_oeminfo UNUSED times 10 dw 0 ; e_res2 UNUSED dd pesig ; e_lfanew But what about doing it to a pre-compiled binary? I just used CFF explorer and HXD. Jot down the ‘e_lfanew’ field offset and zero out the entries between the PE header, the MZ field, and the ‘e_lfanew’ field: The malware does code running modification and is surprisingly sophisticated, but this blog post is long enough. I’m done for now. The next post will be much more interesting, however its unfinished and needs more research. Except it soon. This entry was posted on Saturday, November 22nd, 2014 at 1:51 pm and is filed under code, Joe you evil bastard, reversing. You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed. Sursa: assembly, c-sharp, anti-sandbox, anti-antivirus, anti-debug, and malware research « Joe's Security Blog Edited November 22, 2014 by Nytro Quote