VC dll注入基础教程新手级
进行DLL注入的三种方法

}
//---------------------------------------
// 安装钩子函数
bool __declspec(dllexport) __stdcall SetHook(DWORD dwThreadId)
{
if (dwThreadId != 0)
{
// 因为没有适当的工具可以取得线程ID,也为了简单起见,所以这里新创建了一个记事本进程,以便取得它的线程ID,对其安装钩子,把我们的DLL注入到记事本进程中。
bRet = CreateProcess(NULL,
"c:\\winnt\\system32\\notepad.exe",
}
return true;
}
// 钩子函数
LRESULT CALLBACK __declspec(dllexport) __stdcall
MyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// 因为只是演示DLL注入,所以这里什么也不做,交给系统处理
return;
C# dll注入方法之介绍

C# dll注入方法之介绍本文带着读者共同体验C# DLL注入之旅事实上dll注入很简单,无非就是调用virtualAllocEx,WriteProcessMemory,OpenProcess,CreateRemoteThread等API函数,因为我是学c#的,所以也想看一下c# dll注入这方面的文章,但在网上找了半天,没有找到一篇,也许是c#刚兴起的缘故,学c#的并不多,没办法,只好自己移植一下,因为凡是用到API函数,所有的编程的语言都是相同的,这就为我们的移植带来了方便,学c#的一般应该对API的调用概念很淡,因为c#通常不会去调用API函数,因为这些已经被封装了,在vb,vc++等语言中要结束一个进程,首先就必须要得到这个进程的句柄,然后才能进行相应的关闭进程等操作,得到句柄要用到OpenProcess API函数,结束进程要用到TerminateProcess API函数,但是在c#中你根本不需要知道这些API函数就能完成同样的功能,所以你要是想了解一下API的相关知识,学一点vb是一个很好的选择。
好了!下面就开始我们的c# dll注入之旅吧!首先需要加入以下API函数:[DllImport("kernel32.dll")]public static extern int VirtualAllocEx(IntPtr hwnd, int lpaddress, i nt size, int type, int tect);[DllImport("kernel32.dll")]public static extern int WriteProcessMemory(IntPtr hwnd, int baseaddr ess, string buffer, int nsize, int filewriten );[DllImport("kernel32.dll")]public static extern int GetProcAddress(int hwnd, string lpname);[DllImport("kernel32.dll")]public static extern int GetModuleHandleA(string name);[DllImport("kernel32.dll")]public static extern int CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);C#声明API比较复杂,因为是调用非托管的dll,所以要用到DllImport来调用非托管的dll,他还有很多属性在这就不多说了,网上有很介绍,可以去查一下,不过c#调用自身的变得动态链接库是倒是很方便,直接加个引用就ok了,调用dll要用的一个引用:using System.Runtime.InteropServices;这个不要忘了加上,下面是编好的所有代码:ing System;ing System.Collections.Generic;ing ponentModel;ing System.Data;ing System.Drawing;ing System.Text;ing System.Windows.Forms;ing System.Runtime.InteropServices;ing System.Diagnostics;space dllinject11.{12.public partial class Form1 : Form13.{14.[DllImport("kernel32.dll")] //声明API函数15.public static extern int VirtualAllocEx(IntPtr hwnd, int lpad dress, int size, int type, int tect);16.[DllImport("kernel32.dll")]17.public static extern int WriteProcessMemory(IntPtr hwnd, int baseaddress, string buffer, int nsize, int filewriten );18.[DllImport("kernel32.dll")]19.public static extern int GetProcAddress(int hwnd, string lpna me);20.[DllImport("kernel32.dll")]21.public static extern int GetModuleHandleA(string name);22.[DllImport("kernel32.dll")]23.public static extern int CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);24.public Form1()25.{26.InitializeComponent();27.}28.29.private void button1_Click(object sender, EventArgs e)30.{31.int ok1;32.//int ok2;33.//int hwnd;34.int baseaddress;35.int temp=0;36.int hack;37.int yan;38.string dllname;39.dllname = "c:\\dll.dll";40.int dlllength;41.dlllength = dllname.Length + 1;42.Process[] pname = Process.GetProcesses(); //取得所有进程43.foreach (Process name in pname) //遍历进程44.{45.//MessageBox.Show(name.ProcessName.ToLower());46.if (name.ProcessName.ToLower().IndexOf("notepad") != -1) //所示记事本,那么下面开始注入47.{48.49.baseaddress = VirtualAllocEx(name.Handle, 0, dlllength , 4096 , 4); //申请内存空间50.if (baseaddress == 0) //返回0则操作失败,下面都是51.{52.MessageBox.Show("申请内存空间失败!!");53.Application.Exit();54.}55.ok1 = WriteProcessMemory(name.Handle, baseaddress, dllname, d lllength, temp); //写内存56.if (ok1 == 0)57.{58.59.MessageBox.Show("写内存失败!!");60.Application.Exit();61.}62.hack = GetProcAddress(GetModuleHandleA("Kernel32"), "LoadLibr aryA"); //取得loadlibarary在kernek32.dll地址63.if (hack == 0)64.{65.MessageBox.Show("无法取得函数的入口点!!");66.Application.Exit();67.}68.yan = CreateRemoteThread(name.Handle, 0, 0, hack, baseaddress , 0, temp); //创建远程线程。
一步一步教用VC和VB调用C++ DLL

一步一步教你用VC和VB调用C++ DLL从VC++应用程序调用C++ DLL的函数Visual Studio 6 使创建包含函数或类的动态连接库(DLL) 变得非常容易.第一步打开Visual Studio 然后选择File | New菜单项:选择Win32 Dynamic Link Library, 输入工程名, 敲OK.选择A DLL that exports some symbols 并单击Finish.在File View里你会看到如下的工程文件:第二步在Test.cpp里,你将看到如下代码:// Test.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "Test.h"BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_ call,LPVOID lpReserved){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;}// This is an example of an exported variableTEST_API int nTest=0;// This is an example of an exported function.TEST_API int fnTest(void){return 42;}// This is the constructor of a class that has been exported.// see Test.h for the class definitionCTest::CTest(){return;}Test.cpp 包含了fnTest 和 CTest::CTest.如果你现在编译Test.dll, 你将会得到一个可以被其他VC++应用程序直接调用的DLL. 允许其他VC++程序调用的关键机制?( key mechanism)就包含在Test.h中:// The following ifdef block is the standard way of creating macros// which make exporting from a DLL simpler. All files within this DLL// are compiled with the TEST_EXPORTS symbol defined on the command line.// This symbol should not be defined on any project that uses this DLL.// This way any other project whose source files include this file see // TEST_APIfunctions as being imported from a DLL, whereas this DLL// sees symbols defined with this macro as being exported.#ifdef TEST_EXPORTS#define TEST_API __declspec(dllexport)#else#define TEST_API__declspec(dllimport)#endif// This class is exported from the Test.dll 共4页第1页第2页第3页第4页class TEST_API CTest{public:CTest(void);// TODO: add your methods here.};extern TEST_API int nTest;TEST_API int fnTest(void);这里面发生了什么? #ifdef TEST_EXPORTS是什么意思? TEST_EXPORTS又是在哪定义的?TEST_EXPORTS如果被定义, 那么TEST_API将会被定义为__declspec(dllexport) (DLL导出),否则,将会被定义为__declspec(dllimport)(DLL导入). 这将影响到后边定义的Ctest类是导出类还是导入类. 这意味着如果我们需要导出的时候,我们就得定义TEST_EXPORTS.当一个V C++应用程序要访问这个DLL的时候,可以将Test.lib链接进去,它包含了DLL的导出符号.第三步TEST_EXPORTS在哪里被定义了呢? DLL wizard干了一件我讨厌的事,它把TEST_EXPORTS 放到了命令行里. 选择Project | Settings | C/C++ | General,你将看到工程选项:当然了,这个办法是可行的. 但是它却容易让人忽计,并且可能导致维护上的麻烦. 我比较喜欢清楚明白的定义TEST_EXPORTS : 从项目选项里边去掉/D "TEST_EXPORTS",然后在Test.cpp里来定义它:// Test.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#define TEST_EXPORTS // <=== ADD THIS LINE#include "Test.h"BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){...注意#define TEST_EXPORTS在#include "Test.h"前边. 所以,它定义要在头文件里.现在,可以像先前那样重新编译我们的Test.dll, 我们将得到一个可以被其他VC应用程序所调用的DLL.第四步我们如何调用DLL里的函数呢? 举个例子吧, 我用VS创建一个示例. 选MFC AppWizard (exe),输入项目名字,然后点OK. 选择基于对话框. 然后点Finish. 打开XXXDlg.cpp(XXX是你的工程名字.) 找到OnInitDialog()成员函数, 敲进去如下的代码:...// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// code to test Test.dll function:int n = fnTest(); // <=== ADD THIS LINE// code to test the CTest class:CTesttest;// <=== ADD THIS LINEreturn TRUE; // return TRUE unless you set the focus to a control}第五步我们还没写完代码呢, 现在要把Test.h这个DLL的头文件包含进去:// TestExeDlg.cpp : implementation file//#include "stdafx.h"#include "TestExe.h"#include "TestExeDlg.h"#include"Test.h" // <=== ADD THIS LINE...第六步如果你想赶时间做一个演示的话, 你可能会尝试只是拷贝DLL的test.h 到你的项目目录里去,那么编译器会找到它. 但是当项目很大的时候,这可不是个好主意, 因为当你更新你的DLL文件时,可能会遇上危险.比如忘了拷贝它到你的exe的目录中去. 这里有个简单的方法来解决这个问题: 选择Project | Settings | C/C++ | Settings | Preprocessor, 并且添加Additional include directories: (DLL工程的目录)提示这样做实际上是假设DLL项目和EXE项目拥有同一个项目目录.现在当我编译的时候, 我得到了一个linker errors!!Deleting intermediate files and output files for project 'TestExe - Win32 Debug'.--------------------Configuration: TestExe - Win32 Debug--------------------Compiling resources...Compiling...StdAfx.cppCompiling...TestExe.cppTestExeDlg.cppGenerating Code...Linking...TestExeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall CTest::CTest(void)" (__imp_??0CTest@@QAE@XZ)TestExeDlg.obj : error LNK2001: unresolved external symbol "__declspec(dllimport)int __cdecl fnTest(void)" (__imp_?fnTest@@YAHXZ)Debug/TestExe.exe : fatal error LNK1120: 2 unresolved externalsError executing link.exe.TestExe.exe - 3 error(s), 0 warning(s)第七步虽然我已经告诉编译器DLL符号啦,但是链接器还不知道. 所以我们必须告诉链接器.. 选择Project | Settings | Link,把DLL的lib文件加到Object/library modules里边去:----------------------------------------------第八步好啦,现在编译通过. 在我们运行程序前,别忘了一件事: 把Test.dll拷贝到EXE的目录里去.第九步接下来,可以放一个断点到OnInitDialog()函数里去, 点GO(F5)调试运行:可以看到, fnTest返回了42, 和我们预测的一样. CTest类也可以用类似的方法来测试.要点.∙VS的工程向导为我们创建VC++DLL提供了很好的开始.∙函数,类, 和变量可以从DLL中导出.∙使用#define预处理器定义, 一个头文件将可以被DLL 和应用程序共同使用.∙DLL导出它的符号,并且应用程序导入这个DLL符号. 当编译应用程序时,编译器通过头文件看到的DLL符号, 当链接应用程序时, 链接器通过导入库(Test.lib)看到DLL符号.∙当执行应用程序时,DLL必须放到和EXE相同的目录中去. DLL也可以放到windows或者system目录中,这样也是可行的, 但是它经常引起某些问题, 所以应该避免这样使用和exe文件. 如果这样做的话,我们怎么告诉链接器找到lib文件呢? 有两种方法来做:1. 选择Tools | Options | Directories and set Show directories for为"Library files". 在下边添加上我们工程所使用的Lib文件的路径.1. 2. 另一种办法是,选择Project | Settings | Link, 选category为Input ,在下边的Additional library path 筐里输入工程使用的lib文件的所在路径.哪种方法更好一点呢?这取决于你的开发环境. 第一种方法要求整个工程要共享的设置目录路径, 并且所有要求所有的开发者的VS都必须设置到这些路径.第二种方法允许每个工程定制自己的路径,并且在工程中被储存,如果开发者的计算机上存放了同样的目录,那么每个开发者都可以签出工程并且设计. ,这样可以避免在每台机器上都去设置同样的路径.到现在,我还没有说怎样指定要使用的LIB文件, 我的办法是在DLL的Test.h中添加两行,现在它看起来像下边的样子:#ifdef TEST_EXPORTS #define TEST_API__declspec(dllexport)#else #define TEST_API__declspec(dllimport) #pragma message("automatic link to Test.lib") // <== add this line #pragma comment(lib, "Test.lib") // <== add this line#endif// This class is exported from the Test.dllclass TEST_API CTest{public:CTest(void);};extern TEST_API int nTest;TEST_API int fnTest(void);这样做,保证了当工程包含DLL的头文件时, 它会自动的把DLL 的lib链接进去,我们可以从VS的OUTPUT窗口看到#pragma message给我们的传达的"automatic link to Test.lib"这个消息.(PS:原文在这里/dll/XDllPt1.aspdemo也可以在这里下载到)。
vc的dll基本用法2

vc的dll基本用法2==MICROSOFT基础类库:CaptureEncode项目概述===应用程序向导已为您创建了这个CaptureEncode应用程序。
此应用程序不仅演示Microsoft基础类的基本使用方法,还可作为您编写应用程序的起点。
本文件概要介绍组成CaptureEncode应用程序的每个文件的内容。
CaptureEncode.vcproj这是使用应用程序向导生成的VC++项目的主项目文件。
它包含生成该文件的Visual C++的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
CaptureEncode.h这是应用程序的主要头文件。
它包括其他项目特定的头文件(包括Resource.h),并声明CCaptureEncodeApp应用程序类。
CaptureEncode.cpp这是包含应用程序类CCaptureEncodeApp的主要应用程序源文件。
CaptureEncode.rc这是程序使用的所有Microsoft Windows资源的列表。
它包括RES子目录中存储的图标、位图和光标。
此文件可以直接在Microsoft Visual C++中进行编辑。
项目资源位于2052中。
res\CaptureEncode.ico这是用作应用程序图标的图标文件。
此图标包括在主要资源文件CaptureEncode.rc中。
res\CaptureEncode.rc2此文件包含不在Microsoft Visual C++中进行编辑的资源。
您应该将不可由资源编辑器编辑的所有资源放在此文件中。
///////////////////////////////////////////////////////////////// ////////////应用程序向导创建一个对话框类:CaptureEncodeDlg.h,CaptureEncodeDlg.cpp-对话框这些文件包含CCaptureEncodeDlg类。
从零开始学VC系列教程完整版

从零开始学VC系列教程一.信息显示实验题外话:第一次写教程,不知道该怎么开始.以前见过的教程可能都会介绍比较多的理论然后才开始讲实际操作,我想对于VC,理论讲得太多大家可能更糊涂,所以选择了这个方案,我们先一步步照着做,每一次只介绍一两个知识点,并且把理论放在后面说明,希望大家能喜欢这种方式,并对这种方式提出意见和建议,以便以后章节更适合大家的学习.或许我写的还不能称之为教程,只是一些操作步骤及说明,通过这些练习,希望能使大家对VC有一个新的认识.VC的功能是十分强大的,但我们一般并不会用到所有的功能,就像大家熟悉的KeilC一样,其实Keil功能也是很多的,平时也没见谁把Keil的功能都用到了.基于此,我写的这个教程可能在VC专业人士看来比较简单.不是要班门弄斧,而是希望推行上位机技术,形成一个氛围让大家来学习交流,PC机与下位机结合毕竟也是发展的一个方向.望高手谅解小辈的不自量力.同时,我们结合单片机编程,让大家明白上位机控制方法及原理,当然这是今后章节的内容了.本节内容:学会在文本框中显示文本,学会弹出式对话框使用.学习目的:信息显示是人机交互的基础,同时,信息显示也为以后的程序调试打下基础.1.新建工程.打开点击[文件]->[新建],弹出如下对话框.在工程选项中选择MFC AppWizard[exe],选择好工程存入的位置,然后在工程名称中填入工程的名称,例如Eg01,填入Eg01后.VC会在我们选择的路径后自动加入一个以工程名命名的文件夹作为工程目录.完成按[确定]就会进入工程向导,出现以下的提示.在这个我们选择[基于对话框]就行了.单文档及多文档方式会在以后详细介绍.这里也简要说明一下.①单文档.程序一次只能处理一个文档对象(文件).像写字板,记事本等.②多文档.程序一次可以处理多个对象(文件),像word之类的,可以同时打开多个文件.③基本对话框.程序一般用于处理一些比较小的,工具型的软件.像双龙的ISP下载软件, Easy 51Pro等都是基于对话框.一些不是很复杂的工业软件也通常可以用基于对话框的形式,这种方式的优点是所见即所得,一些控件可以像VB一样拖到工作区就行了.选好以后直接按[完成]就可以了.至于[下一步]的向导,这里我们先不管.然后会进入以下的画面.其中红色及绿色是我的标注,看不清图片可以下载图片放大.选中静态文本框[TODO:在这里设置对话框控制],单击指标右键,在弹出的快捷菜单中选择[属性Properties]菜单项,弹出如下对话框修改IDC_STATIC为IDC_FIRSTLABEL,标题可以写为”第一个应用程序”然后关闭这个对话框,就可以看到刚才的静态文本框内容变为”第一个应用程序”了.在刚才的操作中,我们将静态文本框的ID改为了IDC_FIRSTLABEL,在VC中,ID是控件的标志,不能有相同的ID出现,但允许多个名为IDC_STATIC的ID号.所以,一般并不把文件名命为IDC_STATIC,除非以后我们不想在程序中改变这个控件的属性.有一些控制,例如GroupBox一般并不在程序中改变什么,所以不改变其ID号.ID是程序访问控件的标识,所以一个应用程序中不能有重复ID.按下来我们要添加一个按钮.用鼠标将控件条上的按钮拖到对话框上,可以看到对话框上多了一个按钮. 用上叙方法,改变按钮ID为IDC_BTN1,标题改为”显示”,这样就做好一个按钮了.下面我们为按钮添加代码.双击按钮,会出现以下的提示框.按[OK]为按钮添加响应函数,出面以下画面void CEg01Dlg::OnBtn1(){然,现在还没有响应.现在我们添加一个事件,让这个按钮按下后上面的静态文本框的内容变为”串口号:COM1 波特率:57600”把上面的代码改为void CEg01Dlg::OnBtn1(){57600”果编译通过,按F5运行,可以看到程序运行后的对话框按下按钮,可以看到上面的静态文本框的内容改变了.那么恭喜你,完成我们这个例子的第一步操作了.当然,我这里的对话框看起来没那么高,大家可以调一下高度.怎么退回到控件编辑状态呢首先,我们单击选项卡中的[ResorceView],现在大家只能看到[Reso…]看到IDD_EG01_DIALG了吧,这个其实也是一个ID,是我们对话框的ID,如果大家改一下对话框的ID,就可以看到这里的ID也变了.在VC中,所有的控件都认为是窗体,只是形式不同.双击IDD_EG01_DIALG就可以看到我们刚才的控制编辑状态了.双击[显示]按钮又可以回到代码状态.刚才的例子很简单,却是我们以后会用得最多的.下面我们来分析一下代码void CEg01Dlg::OnBtn1(){57600”面我们提到过,VC中的控件都认为是窗体,所以,对于所有的文本显示,我们都可以用这个函数来做,大家可以试着加入一个编辑框(Edit),同样可以使用用这个函数,只要ID号对了就可以了.VC对大小写敏感,大家要注意大小写.下面我们用另一个方法来实现.把代码改为void CEg01Dlg::OnBtn1(){57600”以看到运行结果是一样的.大家可以看到,我们把变量a定义为CString类型,这个类型我们在C中可能没有见过.CString其实是VC中的一个类.这里我们要引入类的概念了.类跟C语言结构体很像,结构体可以有成员变量,但不能有成员函数,类不但可以有成员变量,还可以有成员函数,并且支持多种方法.在VC中,类用class标识.下面是一个类的定义,我们来分析一下.class CEg01Dlg : public CDialog{public:CString GetPath(void);protected:int GetMax(int a,int b);public:int a;int b;};这个类是我改过的,为了大家看得明白一点.首先,我们从这句class CEg01Dlg : public CDialog知道这个类名是CEg01Dlg,那么public后面的CDialog是什么意思呢CDialog其实也是一个类,是VC中标准对话框类. public CDialog意思是我们定义的这个类CEg01Dlg从CDialog派生,也叫从CDialog继承,从继承这个词语大家就会明白CEg01Dlg不但可以有自身函数,而且还可以用到CDialog里的变量及函数,所以说是继承,就像我们说的继承财产一样,儿子不但可以有自己的钱,还有从老爸那里继承的产财,这些钱都能花.所以,我们也叫CDialog为父类(不是爸类啊),把CEg01Dlg称为子类.当然,这是相对的.如果再定义一个类从CEg01Dlg派生,那么CEg01Dlg也就是父类,派生出来的类就是子类.这段可能有点难明白,大家可以慢慢体会.我们再回到CString上面来,这个类不是派生的,所以也没有父类了.用CString定义一个变量a,我们称为类变量,CString有很强大的功能,我们这里只用到一个功能,就是字符串,a可以是一个不定长度的字符串,所以我们可以给a赋一个任意的字符串而不用关心长度.当然,我们也可以用int StringLen=();来获得这个字符串的长度.从这句可以看到,GetLength()是类CString里的一个函数.大家可能又会关心一个问题,怎么把长度显示出来呢我们把代码改为void CEg01Dlg::OnBtn1(){式化后的字符串还是存放在a中,在这里,我们还用到了一个新的函数MessageBox();我们只是用了这个函数最简单的用法,显示一个字符串.MessageBox用于弹出一个提示对话框.查查MSDN就知道,函数原型是int MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption= NULL, UINT nType= MB_OK );在VC里面,函数可以有默认值,例如LPCTSTR lpszCaption = NULL, UINT nType = MB_OK 变量lpszCaption的默认值是NULL, nType的默认值是MB_OK,这些有默认值的变量我们可以不传值,所以这个函数使用时,最简单的用法就是传lpszText就可以了.如果我们要显示一个固定的字串,可以这样调用MessageBox(“大家好”);是不是很简单啊这一章就写到这里了,一些问题大家可以提.未尽知识点,会在以后再详细介绍.从零开始学VC系列教程二. 对话框及常用控件实验恭喜你,进入VC学习的第二节了.这一节是人机交互的基础.所谓人机交互,说通俗点就是与机器对话.然而我们现在的技术还不能像科幻片里一样与机器人直接说话就行了.所以,我们的操作意图还得通过文本输入,命令按钮等等来实现.本节内容:学会对话框调用及一些常用控件的使用方法.学习目的:学习人机交互,为软件开发提供界面基础.1.新建工程.参考第一节的方法新建一个工程,名字为Eg02完成后如下图细心的朋友一定会发现.新建的工程里还有一个对话框,ID名是IDD_ABOUTBOX这个是做什么用的呢我们用到的软件都会有一个版权声明.通过第一章的学习,大家应该知道怎么观看这个IDD_ABOUTBOX对话框了吧.没错!双击IDD_ABOUTBOX就可以了.我们会看到如下的一个对话框这就是我们这个程序的关于对话框,一般用于版权声明及版本号标识.大家看到的这个对话框里有两个静态文本框和一个图像框(Picture),静态文本框我们在前一节已经介绍过了.大家可以修改一下版权所有这一行,填什么都可以,签个大名也行.完成以后你一定想看看效果,这个对话框怎么打开呢其实VC已经为我们做好了.先按F7编译,然后按F5运行.大家可以看到程序运行了.单击应用程序图标,就会出现一个菜单,选最后一个[关于Eg02],关于对话框就弹出来了.当然,这是系统为我们做好的.自己怎么在程序中调用这个对话框呢为了演示,首先参考第一节的内容添加一个按钮,然后把按钮的ID改为IDC_BTN_ABOUTME,把标题,也就是Caption改为[关于].最终效果如下下面我们为按钮添加代码.相信大家一定还记得怎么进入代码吧..对了,双击[关于]按钮,在弹出的对话框中点[确定]就可以了.为了让大家更好的理解下面的操作,我们先要解释一下关于对话框的类.VC向导会为关于对话框建立一个类,大家看看下面的图单击标签ClassView(这里显示的是[Class…])就可以看到Eg02这个应用程序的类.第一个CAboutDlg就是关于对话框的类.CEg02Dlg对应IDD_EG02_DIALOG.中间的Ceg02App是应用程序的基础类.所以,如果要对关于对话框进行操作,就要用到类CAboutDlg,因为与此有关的函数及变量都封装在CAboutDlg中.看到这里大家可能又糊涂了,没关系,在以后的教程中,通过一些练习大家就会慢慢领会到的.这里还是先为[关于]按钮添加代码.void CEg02Dlg::OnBtnAboutme(){们添加代码成以下所示void CEg02Dlg::OnBtnAboutme(){二句是();功能是调用类CAboutDlg里的一个函数DoModal();这个函数在MSDN里的解释是Call this member function to invoke the modal dialog box and return the dialog-box result when done. This member function handles all interaction with the user while the dialog box is active. This is what makes the dialog box modal; that is, the user cannot interact with other windows until the dialog box is closed.一般我们用于显示一个对话框.其实大家看看CAboutDlg这个类下面,只有两个函数DoModal()这个函数并不在这个里面.第一章我们提到过类的派生和继承.其实CAboutDlg这个类是派生于CDialog类,DoModal()这个函数是CDialog的成员函数,由于CAboutDlg是继承父类CDialog的,所以CDialog里的函数在CAboutDlg中也可以使用.下面我们来说说几个常用控件的使用.首先在IDD_EG02_DIALOG对话框中加入一个Edit(编辑框)控件.Edit一般用于输入输出数据文本.相当于VB里的TextBox.加入Edit控件后,编辑其属性为然后,我们再加一个按钮(PushButton),并编辑其属性为接下来,我们先说一下要实现的效果.很简单,在编辑框里输入一个文本,然后按显示,就把文本显示在静态文本框中.所以,这里要把静态文本编辑框的ID改为IDC_DISPLABEL下面我们为[显示]按钮添加代码void CEg02Dlg::OnBtnShow(){查MSDN就知道函数原型了.int GetDlgItemText(int nID,LPTSTR lpStr,int nMaxCount)const;int GetDlgItemText( int nID, CString& rString ) const;大家看看就觉得奇怪了,怎么有两个原型啊并且一个是传两个参数,另一个是传三个参数.在VC里面,同一个类下是可以存在多个同名函数的,具体调用哪个函数要看参数的不同.在这里我们传入了两个参数,所以VC会调用int GetDlgItemText( int nID, CString& rString) const;这个函数.第一个函数是控件的ID号,第二个是字串.第二个传了地址,所以我们在下一句中用的a已经是获得IDC_EDIT_INPUT的文本了.运行效果如下下面介绍一下进度条的使用以及定时器的使用.我们要实现的效果是进度从0到满格,然后再从0到满格,依次循环.每跳一格间隔500ms,这个时间我们用定时器来实现.首先从控件条里拖出一个进程条到对话框,修改属性如下然后我们要介绍一下VC的定时器.VC里面使用定时器有多种方式,我们先介绍一种作为抛砖引玉首先添加一个Windows消息处理器.消息这个词语可能很陌生,我们会在后面很多次说明.这里先照图做在类管理器里选中Ceg02Dlg这个类,然后点右键,就会弹出一个菜单,选择[Add Windows Message Handler…],接下来会弹出另一个菜单双击WM_TIMER然后按[确定]就可以了.大家会看到,CEg02Dlg类中多了一个函数这个就是VC中的定时器响应函数.然后双击这个函数就进入代码了然后我们为Timer事件添加代码.void CEg02Dlg::OnTimer(UINT nIDEvent){认时,进度条0为空,100为满格.从后的程序大家可以看到,这个变量自加到100就变为0.最难理解的就是((CProgressCtrl*)(GetDlgItem(IDC_PROGRESS)))->SetPos(nPos);首先, GetDlgItem(IDC_PROGRESS)这个函数用来获取IDC_PROGRESS的句柄,在VC里面引入了句柄这个词语,我们将在下一章中对消息和句柄进行详细的说明, 句柄是WINDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。
关于DLL的VC++程序编程方法

关于DLL的VC++程序编程方法
DLL(Dynamic Link Library)是一种通用的动态联接库,它可以将多个应用程序共享一个动态链接库文件。
使用DLL可以
大大减少程序开发时间和空间,以提高代码的复用性和可维护性。
本文将介绍VC++程序编程中使用DLL的方法。
首先,我们必须创建要使用的DLL文件。
在VC++环境中,
我们可以使用“工程”→“添加新项”菜单来创建一个DLL工程。
然后,我们可以根据需要对其进行定制,如添加头文件,函数定义,全局变量声明等。
接下来,请编译DLL文件,生成一个.dll文件。
此时,就可以在我们的程序中使用该.dll文件。
使用DLL中的函数需要调用函数声明,并以此来包含需要调用的内容。
因此,要使用DLL中的函数,首先必须导入该DLL。
在
VC++中可以使用“#import <filename>”语句来导入一个库,其
中<filename>是DLL文件的名称。
导入DLL后,就可以在应
用程序中调用函数了。
在编写代码时,我们需要将传入的参数与DLL函数的参数类
型保持一致,并且最好在函数前面加上"__stdcall",这样可以
避免出现错误。
最后,编译程序,将生成的程序文件和导入的DLL文件放到
同一个文件夹中,就可以使用DLL文件了。
总之,使用DLL可以大大提高程序开发效率,减少重复编写的代码,并具有良好的程序可维护性。
因此,使用DLL是VC++程序编程中不可缺少的一部分,并且应该在程序中使用DLL来提高程序性能和可维护性。
dll编程入门(C++语言)

C++下的DLL编程入门一、编写第一个入门级dll文件1. 新建一个dlltest的dll工程,加入一源文件dlltest.cpp,包含add和subtract两个函数如下:_declspec(dllexport)int add(inta,int b){returna+b;}_declspec(dllexport)int subtract(inta,int b){return a-b;}//----------------------------------------------------------------注意:在函数名前加上_declspec(dllexport),这样编译后在连接的时候才会生成dlltest.lib (引入库文件)和dlltest.exp(输出库文件),并且在命令提示符下用dumpbin命令可以看到导出了哪些函数。
方法:在命令提示符下,转到dll文件所在目录下,输入dumpbin–exports dlltest.dll,列出导出函数如下:这里注意到函数名字已经被改成了?add@@YAHHH@Z,这种现象叫做名字粉碎,是为了支持函数重载而做的。
2.编写一个基于对话框的MFC程序测试DLL,工程名为calldll,放置两个按纽add和subtract,响应按纽消息,调用这个DLL的add和subtract函数。
先添加响应按钮消息的函数OnAdd和OnSubtract,然后在函数所在源文件中写完整函数体如下://extern intadd(int,int);//extern intsubtract(int,int);_declspec(dllimport)int add(int,int);_declspec(dllimport)int subtract(int,int);voidCCalldllDlg::OnAdd(){// TODO: Add your control notification handler code hereCStringstr;str.Format("2+3=%d",add(2,3));MessageBox(str);}voidCCalldllDlg::OnSubtract(){// TODO: Add your control notification handler code hereCStringstr;str.Format("3-2=%d",subtract(3,2));MessageBox(str);}//------------------------------------------------------------这里采用隐式链接的方式加载动态链接库:注意:要用关键字extern先声明这两个函数,表明这两个函数是在外部定义的(不过程序中将它注释掉了)。
vc++ 向其他进程注入代码的三种方法

vc++ 向其他进程注入代码的三种方法导言:我们在Code project()上可以找到许多密码间谍程序(译者注:那些可以看到别的程序中密码框内容的软件),他们都依赖于Windows钩子技术。
要实现这个还有其他的方法吗?有!但是,首先,让我们简单回顾一下我们要实现的目标,以便你能弄清楚我在说什么。
要读取一个控件的内容,不管它是否属于你自己的程序,一般来说需要发送 WM_GETTEXT 消息到那个控件。
这对edit控件也有效,但是有一种情况例外。
如果这个edit控件属于其他进程并且具有 ES_PASSWORD 风格的话,这种方法就不会成功。
只有“拥有(OWNS)”这个密码控件的进程才可以用 WM_GETTEXT 取得它的内容。
所以,我们的问题就是:如何让下面这句代码在其他进程的地址空间中运行起来:::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );一般来说,这个问题有三种可能的解决方案:1. 把你的代码放到一个DLL中;然后用 windows 钩子把它映射到远程进程。
2. 把你的代码放到一个DLL中;然后用 CreateRemoteThread 和 LoadLibrary 把它映射到远程进程。
3. 不用DLL,直接复制你的代码到远程进程(使用WriteProcessMemory)并且用CreateRemoteThread执行之。
在这里有详细的说明:Ⅰ. Windows 钩子示例程序:HookSpy 和 HookInjExWindows钩子的主要作用就是监视某个线程的消息流动。
一般可分为:1.局部钩子,只监视你自己进程中某个线程的消息流动。
2.远程钩子,又可以分为:a.特定线程的,监视别的进程中某个线程的消息;b.系统级的,监视整个系统中正在运行的所有线程的消息。
如果被挂钩(监视)的线程属于别的进程(情况2a和2b),你的钩子过程(hook procedure)必须放在一个动态连接库(DLL)中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学习各种高级外挂制作技术,马上去百度搜索(魔鬼作坊),点击第一个站进入,快速成为做挂达人。
首先要明白什么是线程说到线程就不得不提到进程SDK文档里是这样描述的进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的代码、数据和其他系统资源。
一个进程包含了一个或者多个运行在此进程内的线程。
说白了,其实进程就是一个磁盘上的程序载入内存执行后的东西打开任务管理器看看,里面有好多进程...从定义上看出进程一定要有线程,线程是进程内存中的独立实体。
讲了这么多废话其实就是想说程序运行后就变成了进程,你的代码由线程来执行。
回到正题上,线程插入是什么呢?就是把一个线程弄到别的进程执行你也许觉得奇怪,自己不是有个进程好好的吗?其实这个作用大了,先说说开头提到的木马一来,有些比较由经验的用户有时会打开任务管理器,发现陌生进程?!想想你的木马还能活吗?那么插入Explorer等关键进程,你还想用电脑的话最好不要杀那个进程(不信试试)二来,大家现在都装防火墙了,网络连接经常会被虑掉,木马岂不是没用了?好,插入IE,防火墙想虑?除非你不想看网页当然,还有很多用处,比如插入系统级别的进程,哈哈,我们有Ring0权限了,(不要告诉我你不知道Ring0...就是连物理内存都可以写的超级权限)HookAPI也需要把代码注入别的进程知道了他的作用想知道怎么实现吧?别着急,慢慢来首先,这个应该属于系统编程,系统编程就不能不知道APIAPI是什么?简单点讲就是Windows为我们提供的一些函数,利用他们我们可以做很多事情Delphi花了很大力气用VCL还有一些乱七八糟的类把让我们可以尽量不要API所以会编程序但不了解API还是可能的API被封装在kernel32.dll、user32.dll等动态链接库里,程序使用时候把DLL映射到自己的内存了编写的时候我们通常需要从DLL导出这些函数function Beep;external'kernel32.dll'name'Beep';这样导出一个beep函数当然,实际上不要这么麻烦Delphi已经把这些导出声明写在一些单元里面了(比如windows单元)uses windows后就可以直接用了(而且建立窗口时候默认就会引用很多单元)所以实际上我们可以直接用的这个理解一下就好了开始讲线程插入了一般来说线程插入有2种方法1.DLL注入2.直接的远程线程插入DLL注入编写的时候比较简单,方法也多,但有个缺点进程会多出个模块来,可能被发现远程线程是直接修改对方内存的方法,虽然隐蔽性好,但是不小心可能会出点问题,比如你让不能有界面的进程弹出个窗口,不能上网的进程开个端口,那就等着系统崩溃吧今天重点讲DLL注入首先要知道什么是DLL,dll就是动态链接库,大家应该知道吧?怎么编写DLL呢?和写普通程序差不多是一样的新建一个工程,选DLL Wizard发现了吧?除了program改成library剩下几乎是一样的,只是需要程序加载他的入口点我们先编写个简单的DLLlibrary TestDll;usesWindows;{$R*.res}procedure func_a;beginMessageBox(0,'I love delphi','Function form Tset DLL',0);end;procedure func_b(MSG:pchar);beginMessageBox(0,MSG,'Function form Tset DLL',0);end;beginfunc_a;func_b('I like it too!');end.就是那个testdll.dpr看得懂吧,弹出2个信息框好了保存下,F9运行..出错,哈哈,DLL是不能直接运行的那怎么办?编译下(按过F9就不用了,也会编译好)看见那个DLL了吧?我们弄个程序加载它的入口点新建一个普通程序加一个按钮按钮事件只要写一句loadlibrary('testdll.dll');MainShow.dpr运行,单击按钮,怎么养?弹出东西了吧当然DLL还可以做函数库,资源库等今天暂不讨论现在DLL懂得写了吧?就是program改成library而已你可以写自己的程序了DLL会写了,现在的问题就是怎么注入了我们目的只是让对方的程序运行一句loadlibrary('testdll.dll');而已一切就OK了通常有这么几种注入方法1.利用全局消息钩子Win32下程序一般都要用收发消息用钩子函数下全局钩子,程序收到任何消息都加载我们的DLL的入口点当然,用这种方法DLL进入后要判断自己是不是被插进目标进程是的话,执行代码不是退出这个方法很麻烦但通用性很好,只要WINDOWS都可以用(但是有的系统进程消息是勾不住的,所以注入不了)早期的DLL注入大部分是用这个原理实现的2.写注册表写HKEY_LOCAL_MAHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs但是只能是NT下,而且必须是调用过user32.dll(Windows的一个内核,只要有界面的程序都调用它)的程序,在开机后所有程序会自动加载DLL,但是这个dll不能被卸载,而且不能调用某些函数,不然系统会挂掉(有危险性哦)不推荐使用3.利用远程线程注入来实现DLL注入只要能打开句柄,就能成功(强吧?)而且实现起来比较简单缺点就是9X内核的有点难度(也不是很困难)我们今天就讲利用远程线程注入来实现DLL注入吧!你可能要问,既然刚才说了远程线程可以直接注入一个线程,为什么还要多此一举反过来再调用DLL呢?这是因为,远程线程技术一般是直接对目标程序的内存进行操作我们知道不同程序的虚拟内存是不一样的所以很多函数的地址不一定一样而程序运行的时候实际上是Call函数地址进行函数调用的所以我们要注意计算很多偏移之类的这是非常烦琐的事情而且像上面说的让不能有界面的进程弹出个窗口,那就不好玩了而DLL呢?DLL调用时其实是被映射到进程内存里面DLL拥有自己的导入表、资源、函数等东西,实际上就是一个完整的程序映入内存后和执行一个程序效果是一样的这样我们就不用考虑那些乱七八糟的东西,只要安心的写功能即可好了,要明白远程线程首先当然要把程序本地线程搞清楚了不知道大家编多线程程序的时候是不是都用tthread类?反正我是不喜欢那个我们看看Windows给我们的原始API吧(tthread类也是用它写的)function CreateThread(lpThreadAttributes:Pointer;//安全指针一般nil就可以了dwStackSize:DWORD;//线程初始化尺寸,一般用0,获得与主线程一样尺寸(不够自己会增加,别担心)lpStartAddress:TFNThreadStartRoutine;//一个指向要执行线程函数的指针,这个函数必须遵守stdcall约定,并且可带一个参数,参数必须是指针类型lpParameter:Pointer;//函数的参数dwCreationFlags:DWORD;//控制创建标志,用0表示线程立刻执行var lpThreadId:DWORD)//返回标识变量我觉得没什么用,反正句柄都有了:THandle;//返回线程的句柄stdcall;//标准调用Windows下API一般都是标准调用大家先看下看起来似乎比较复杂,等下举个例子我们把DLL源码里面的func_b拷到刚才那个EXE上稍微修改下procedure func_b(MSG:pchar);stdcall;beginMessageBox(0,MSG,'Function form Tset DLL',0);sleep(10000);//线程暂停N久(不超过10s)end;加上2个按钮第一个procedure TForm1.Button2Click(Sender:TObject);beginfunc_b('123');end;第二个procedure TForm1.Button3Click(Sender:TObject);var tid:longword;//放返回值,不放她不让执行,郁闷str:pchar;//便于获得pointerbeginstr:='123';createthread(nil,0,@func_b,//函数名前面加@是得到函数指针pointer(str),//虽然str也是指针,但是delphi就是要pointer型的,那就转一下类型0,tid);//tid纯属放着占格式的,一般我们用不到end;//上面CreateThread看得懂吧,几乎都是默认设置,以后套下去用就是了实际上都是调用func_b,只是第二个过程用了信新线程但是效果是不一样的第一个按钮按下弹出窗口后,程序卡死了(暂停10000)第二个却不会为什么呢?我们可以这样理解窗口看做一个主线程,执行func_b,弹出窗口,然后主线程挂起,于是卡死了而第二个过程创建一个新线程,新线程执行func_b,弹出窗口,挂起10000,但是由于主线程没有挂起,所以看起来关掉窗口后没什么事情发生(实际上那个线程还在偷偷执行,直到线程代码运行完,只是它卡死不会影响你)这个如果明白了那么下面就容易理解了看看这个函数function CreateRemoteThread(hProcess:THandle;lpThreadAttributes:Pointer;dwStackSize:DWORD;lpStartAddress:TFNThreadStartRoutine;lpParameter:Pointer;dwCreationFlags:DWORD;var lpThreadId:DWORD):THandle;stdcall;除了函数名不一样,下面的参数多了个hProcess:THandle;,剩下的完全一样呵呵,这个东西就是本节课的关键了先看函数名就知道是干什么用的了‘创建远程线程’用法和刚才基本一致就是hProcess:THandle是什么呢?这里要填的是被注入线进程的句柄什么是句柄?打个比方,对象是一个门,句柄就是那个把手,通过句柄我们可以对门进行操作也就是说我们利用句柄来操作某些东西(包括进程、线程等等)你有没有注意到,CreateThread和CreateRemoteThread都返回一个THandle,也就是线程的句柄还有loadlibrary也会返回DLL的句柄,我们可以利用他们对相关对象进行操作那么怎么获得进程句柄呢?一般采用先得到进程PID再用下面的函数取得句柄function OpenProcess(dwDesiredAccess:DWORD;//访问标志一般填写PROCESS_ALL_ACCESS,这样这个句柄可以获得最大操作权限bInheritHandle:BOOL;//可否继承,这个跟子程序有关,无所谓了,填false和true都可以,反正我们自己能操作久可以dwProcessId:DWORD)://要获得句柄的进程IDTHandle;stdcall;//返回句柄有时候会返回0,说明打开句柄失败了一般是你的权限不够(比如你想对Winlogon这些系统级程序操作)这时候我们需要提升权限一般Debug权限就可以了(其实操作权限里面最高了)提升的过程我写好了直接调用就可以了(修改进程令牌到Debug级别,为什么这样写这里不详细讲了,自己去网上搜索下)procedure GetDebugPrivs;varhToken:THandle;tkp:TTokenPrivileges;retval:dword;beginIf(OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken))thenbeginLookupPrivilegeValue(nil,'SeDebugPrivilege',tkp.Privileges[0].Luid);tkp.PrivilegeCount:=1;tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken,False,tkp,0,nil,retval);end;end;不会晕吧?应该记得我刚才提到了要PID,那怎么得到呢?一般用FindWindow和GetWindowThreadProcessId配合的到这样写先var Pid:longword;//储存那个PIDGetWindowThreadProcessId(FindWindow('Notepad',nil),@PID);这样就找到笔记本的PID,再如'Shell_TrayWnd'可以找到Explorer的窗口类名据说可以用SPY++查询,不过这东西我没见过,呵呵当然还可以枚举进程判断进程名等等这个先告一段落。