7.15生产实习日志

如何对传递多个参数

使用结构体

通过结构体传递多个参数到线程函数中,示例代码展示了如何创建一个结构体并将其作为参数传递给线程函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#include<Windows.h>


typedef struct ThreadArgs {
const char arg1[100];
const char arg2[100];
};
DWORD WINAPI ThreadProc(LPVOID lpParam) {
struct ThreadArgs* myArgs = (struct ThreadArgs*)lpParam;
printf("%s %s", myArgs->arg1, myArgs->arg2);
return 0;
}

int main() {
struct ThreadArgs string = { 0 };
strcpy(string.arg1, "Hello");
strcpy(string.arg2, ",World!");

HANDLE thread = CreateThread(NULL, 0, ThreadProc, &string, 0, 0);

WaitForSingleObject(thread, -1);
return 0;
}

灵活使用指针

利用指针在内存中操作数据,示例代码展示了如何通过指针在内存中存储和读取数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
#include<Windows.h>


DWORD WINAPI ThreadProc(LPVOID lpParam) {
char* data = (char*)lpParam;
printf("%s\n", data);
data = (char*)data + strlen(data) + 1;
printf("%s\n", data);
return 0;
}

int main() {
struct ThreadArgs string = { 0 };
strcpy(string.arg1, "Hello");
strcpy(string.arg2, ",World!");

char data[] = {'F','i','r','s','t','\0','S','e','c','o','n','d','\0'};
char* First = data;
char* Second = First + strlen(First) + 1;
printf("%s\n", First);
printf("%s\n", Second);
HANDLE thread = CreateThread(NULL, 0, ThreadProc, First, 0, 0);

WaitForSingleObject(thread, -1);
return 0;
}

读取文件

通过C++读取二进制文件并在内存中执行其内容。示例代码展示了如何读取DLL文件并将其内容加载到内存中执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<fstream>
#include<iostream>
#include<Windows.h>
#include<stdio.h>
using namespace std;

int main() {
char filename[] = "box.dll";
ifstream infile;
infile.open(filename, ios::out | ios::binary);
infile.seekg(0, infile.end);
int length = infile.tellg();
infile.seekg(0, infile.beg);
char* datath = new char[length];
if (infile.is_open()) {
cout << "reading from the file" << endl;
infile.read(datath, length);
}
LPVOID addr = VirtualAlloc(0, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

memcpy(addr, datath, length);
HANDLE HThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)addr, 0, 0, 0);
WaitForSingleObject(HThread, -1);
}

Linux安装JDK

下载JDK安装包

1
2
cd /usr/local
wget https://download.java.net/java/GA/jdk17.0.1/2a2082e5a09d4267845be086888add4f/12/GPL/openjdk-17.0.1_linux-x64_bin.tar.gz

解压文件

1
2
mkdir /usr/local/jdk
tar -zxvf openjdk-17.0.1_linux-x64_bin.tar.gz -C /usr/local/jdk

配置环境变量

1
vim /etc/profile

在文件末尾添加以下信息

1
2
3
export JAVA_HOME=/usr/local/jdk/jdk-17.0.1
export CLASSPATH=$:CLASSPATH:$JAVA_HOME/lib/
export PATH=$PATH:$JAVA_HOME/bin

刷新配置

1
source /etc/profile

检查配置

1
java --version

初始ShellCode

Shellcode多种加载方式与分离

shellcode的执行,本质就是内存执行

首先,如果要执行一段代码,那么存储代码的内存必须拥有可执行权限。

最简单的exe(数据段,代码段)

数据段的权限(可读,可写)

代码段的权限(可读,可执行)

(可读,可写,可执行)

存放shellcode的内存需要X权限

  • 声明数据段可执行
1
2
#pragma comment(linker, "/section:.data,RWE")
unsigned char buf[] = "shellcode";
  • 申请可执行内存
1
2
3
4
LPVOID exec = VirtualAlloc(NULL, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, shellcode, sizeof shellcode);
SIZE_T size;
WriteProcessMemory(GetCurrentProcess(), exec, shellcode, sizeof shellcode, &size);

指针执行

1
2
3
(*(int(*)()) shellcode_addr)();
(*(void(*)()) shellcode_addr)();
((void(*)(void)) & buf)();

直接指针执行

1
2
3
4
5
6
7
8
#include <Windows.h>
#include <stdio.h>
#pragma comment(linker, "/section:.data,RWE")
unsigned char buf[] = "你的shellcode";
int main()
{
((void(*)(void)) & buf)();
}

内存指针执行

1
2
3
4
5
6
7
8
9
include <Windows.h>
include <stdio.h>
int main()
{
unsigned char buf[] = "shellcode";
void* exec = VirtualAlloc(0, sizeof buf, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, buf, sizeof buf);
((void(*)())exec)();
}