超过用户使用预期的代码叫做恶意代码
恶意代码在windows中常见的运行方式
在硬盘中存在
不在硬盘中存在(比如直接在内存中)
0x01、C++
首先安装visual studio

测试是否正常使用
#include<iostream> //导入库
using namespace std; //命名空间,原来处理标准使用词
int main() {
cout << "Hello world";
return 0;
}C++七种数据类型
每个字符的占位如下 sizeof(size_t)
可以使用typedef为已有的类型取一个新的名字
// typedef type newname;
typedef int z_int;类型转换(静态)
int a= 1;
static_case<float>(a);类型转换(强制)
int a=1;
char chara = (char)a;定义常量
#define identifier value
const char a ='q';修饰符
signed : 表示变量可以存储负数,对于整型变量来说,signed可以省略
unsigned:表示变量不能存储负数,对于整型变量来说,可以将变量范围扩大一倍
short:表示变量范围比int更小, short int可以缩写short
long:表示变量的范围比int更大, long int 可以缩写为long。
位运算符
多变量的集合
数组
double balance[5] = { 1000.0, 2.0,3.4, 7.0, 50.0 };
double salary = balance[3];
char name[] = "cutecuteye"; //多个字符组成的字符串可以写成字符数组字符串
strcpy(s1,s2);
strcat(s1,s2);
string str1="hello";
string str2="world";
string str = str1+str2;
strlen(str); //返回字符串的长度
strcmp(s1,s2); //s1和s2相同返回0;s1<s2返回小于0;结构体
结构体中建好了一个类型就必须要定义一个对象,外面的结构体就没有这个要求。
struct Books
{
char title[50];
char author[50];
int subject[100];
int book id;
struct PP{
int P1=2;
}PP;
}
//定义
/*
struct是保留字
struct 结构体类型的名字
{
结构体中的变量类型 结构体中的变量名称;
}
*/
//使用
Books Book1;
Book1.book_id=12345;函数
return_type function name(parameter list)
//返回值类型 函数名称 参数类型和参数名
{
body of the function//函数代码
}
函数的调用一定要写在函数定义的下面,不然会报错也可以使用两数声明的方式,如下
#include<iostream>
using namespace std;
int test(int a, int b);
int main(){
int d = test(1,2);
return 0;
}
int test(int a, int b){
int c;
return a+b;
}指针在安全中的两种常用方式
目标数据我们没有权限,但是指针的位置有权限
目标数据我们找不到具体的位置,但是指针的位置是固定的。
windowsAPI
该API是windows操作系统与应用程序的接口
https:/learn.microsoft.com/zh-cn/docs/
使用api实现一个利用注册表开机启动的小程序
#include <windows.h>
#include <iostream>
#include <string>
// 注册表路径,用于设置开机启动
const std::wstring REGISTRY_RUN_PATH = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
// 添加程序到注册表开启开机启动
bool AddToStartup(const std::wstring& appName, const std::wstring& exePath) {
HKEY hKey;
// 打开/创建 注册表键
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_RUN_PATH.c_str(), 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) {
std::wcerr << L"无法打开注册表键\n";
return false;
}
// 写入注册表项
if (RegSetValueEx(hKey, appName.c_str(), 0, REG_SZ,
reinterpret_cast<const BYTE*>(exePath.c_str()),
static_cast<DWORD>((exePath.size() + 1) * sizeof(wchar_t))) != ERROR_SUCCESS) {
std::wcerr << L"无法设置注册表值\n";
RegCloseKey(hKey);
return false;
}
RegCloseKey(hKey);
return true;
}
// 检查是否存在启动项
bool CheckStartup(const std::wstring& appName, std::wstring& exePathOut) {
HKEY hKey;
wchar_t buffer[MAX_PATH];
DWORD bufferSize = sizeof(buffer);
// 打开注册表键
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_RUN_PATH.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
std::wcerr << L"无法打开注册表键\n";
return false;
}
// 查询指定的注册表值
if (RegQueryValueEx(hKey, appName.c_str(), 0, nullptr,
reinterpret_cast<LPBYTE>(buffer), &bufferSize) == ERROR_SUCCESS) {
exePathOut = buffer; // 获取到的路径
RegCloseKey(hKey);
return true;
}
RegCloseKey(hKey);
return false;
}
// 从注册表中移除开机启动项
bool RemoveFromStartup(const std::wstring& appName) {
HKEY hKey;
// 打开注册表键
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_RUN_PATH.c_str(), 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) {
std::wcerr << L"无法打开注册表键\n";
return false;
}
// 删除注册表值
if (RegDeleteValue(hKey, appName.c_str()) != ERROR_SUCCESS) {
std::wcerr << L"无法删除注册表值\n";
RegCloseKey(hKey);
return false;
}
RegCloseKey(hKey);
return true;
}
int main() {
std::wstring appName = L"MyApp"; // 启动项名称
wchar_t exePath[MAX_PATH];
// 获取当前程序路径
if (GetModuleFileName(nullptr, exePath, MAX_PATH) == 0) {
std::wcerr << L"无法获取程序路径\n";
return 1;
}
std::wcout << L"当前程序路径: " << exePath << std::endl;
// 检查是否已经在启动项中
std::wstring existingPath;
if (CheckStartup(appName, existingPath)) {
std::wcout << L"启动项已存在: " << existingPath << std::endl;
} else {
std::wcout << L"启动项不存在,添加中...\n";
if (AddToStartup(appName, exePath)) {
std::wcout << L"成功添加开机启动。\n";
} else {
std::wcerr << L"添加开机启动失败。\n";
return 1;
}
}
// 移除启动项(可注释掉此段代码进行测试)
if (RemoveFromStartup(appName)) {
std::wcout << L"已成功移除启动项。\n";
} else {
std::wcerr << L"移除启动项失败。\n";
}
return 0;
}0x02 DLL
DllMain 函数
DllMain 是 DLL 的入口点,由操作系统调用,它主要用于响应 DLL 的加载和卸载事件。系统会自动调用,无需手动调用或暴露给外部用户。不能用来导出函数给外部调用,它仅供操作系统调用,并用于管理 DLL 的生命周期。
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// 进程加载了 DLL
// 适合执行一次性的初始化代码
break;
case DLL_THREAD_ATTACH:
// 线程加载了 DLL
// 适合执行线程相关的初始化代码
break;
case DLL_THREAD_DETACH:
// 线程正常退出
// 用于释放线程相关的资源
break;
case DLL_PROCESS_DETACH:
// 进程卸载了 DLL
// 释放全局资源、关闭句柄等清理工作
break;
}
return TRUE; // 返回 TRUE 表示初始化成功
}DLL_PROCESS_ATTACH:进程加载了 DLL。 发生在进程启动时(比如调用
LoadLibrary或LoadLibraryEx加载 DLL 时(动态链接)。此状态只影响进程级别,因此通常执行一次初始化。DLL_THREAD_ATTACH:进程中的一个线程加载了 DLL。当进程中的线程被创建时,并且该进程已经加载了 DLL。通常用于进行线程级别的初始化,例如为新线程分配线程局部存储(TLS)。
DLL_THREAD_DETACH:进程中的一个线程正常退出。当线程退出时,卸载 DLL 时会调用此分支。用于清理线程相关资源,例如释放线程局部存储。如果线程是通过
TerminateThread终止的,这个状态不会被触发。DLL_PROCESS_DETACH:进程卸载 DLL。发生在进程结束时(如果 DLL 是静态链接的)或者调用 FreeLibrary 或卸载 DLL 时(动态链接)。
完成编译成dll,类似于如下代码调用即可
#include<windows.h>
void main(){
LoadLibraryA("dll1.dll")
}直接导出函数
通过 __declspec(dllexport) 显式导出一些函数,这些函数可以被外部程序通过 LoadLibrary 和 GetProcAddress 动态加载并调用。提供真正的业务功能,例如计算、工具函数、逻辑操作等。
提供 API 给其他程序使用。出函数仅用于提供功能,并不直接处理 DLL 的生命周期。
#include <windows.h>
#include <iostream>
// 导出函数声明
extern "C" __declspec(dllexport) void HelloWorld()
{
MessageBox(NULL, TEXT("Hello, World!"), TEXT("Message from DLL"), MB_OK);
}调用该dll
#include <windows.h>
#include <iostream>
// 方法类型定义
typedef void (*HelloWorldFunc)();
int main()
{
// 加载 DLL
HINSTANCE hDLL = LoadLibrary(TEXT("SimpleDLL.dll"));
if (hDLL == NULL)
{
std::cerr << "Failed to load DLL\n";
return -1;
}
// 获取导出函数地址
HelloWorldFunc helloWorld = (HelloWorldFunc)GetProcAddress(hDLL, "HelloWorld");
if (helloWorld == NULL)
{
std::cerr << "Failed to find function in DLL\n";
FreeLibrary(hDLL);
return -1;
}
// 调用导出函数
helloWorld();
// 释放 DLL
FreeLibrary(hDLL);
return 0;
}