C# DLL注入技術
前段時間研究了了一下dll注入,雖然這項技術已經被寫爛了,而且現在而言,這項技術已經落後了,基本上程式設計都到核心的級別了,不過再過時的技術對於我們剛學程式設計的菜鳥來說都是新鮮的,我們還是要一點一點的來學,先把基礎的東西學會了,以後才能成為大鳥嗎!,我開始用vb編了一個dll注入的程式,事實上dll注入很簡單,無非就是呼叫virtualAllocEx,WriteProcessMemory,OpenProcess,CreateRemoteThread等API函式,因為我是學c#的,所以也想看一下c#這方面的文章,但在網上找了半天,沒有找到一篇,也許是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, Int32 lpaddress, int size, int type, Int32 tect);
[DllImport("kernel32.dll")]
public static extern Boolean WriteProcessMemory(IntPtr hwnd, int baseaddress, 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 IntPtr CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);
[DllImport("kernel32.dll")]
public static extern Int32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern Boolean VirtualFree(IntPtr lpAddress, Int32 dwSize,Int32 dwFreeType);
public static extern int VirtualAllocEx(IntPtr hwnd, Int32 lpaddress, int size, int type, Int32 tect);
[DllImport("kernel32.dll")]
public static extern Boolean WriteProcessMemory(IntPtr hwnd, int baseaddress, 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 IntPtr CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);
[DllImport("kernel32.dll")]
public static extern Int32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern Boolean VirtualFree(IntPtr lpAddress, Int32 dwSize,Int32 dwFreeType);
C#宣告API比較複雜,因為是呼叫非託管的dll,所以要用到DllImport來呼叫非託管的dll,他還有很多屬性在這就不多說了,網上有很介紹,可以去查一下,不過c#呼叫自身的變得動態連結庫是倒是很方便,直接加個引用就ok了,呼叫dll要用的一個引用:using System.Runtime.InteropServices;這個不要忘了加上,下面是編好的所有程式碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace dllinject
{
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]
public static extern int VirtualAllocEx(IntPtr hwnd, Int32 lpaddress, int size, int type, Int32 tect);
[DllImport("kernel32.dll")]
public static extern Boolean WriteProcessMemory(IntPtr hwnd, int baseaddress, 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 IntPtr CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);
[DllImport("kernel32.dll")]
public static extern Int32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern Boolean VirtualFree(IntPtr lpAddress, Int32 dwSize,Int32 dwFreeType);
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace dllinject
{
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]
public static extern int VirtualAllocEx(IntPtr hwnd, Int32 lpaddress, int size, int type, Int32 tect);
[DllImport("kernel32.dll")]
public static extern Boolean WriteProcessMemory(IntPtr hwnd, int baseaddress, 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 IntPtr CreateRemoteThread(IntPtr hwnd, int attrib, int size, int address, int par, int flags, int threadid);
[DllImport("kernel32.dll")]
public static extern Int32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
[DllImport("kernel32.dll")]
public static extern Boolean VirtualFree(IntPtr lpAddress, Int32 dwSize,Int32 dwFreeType);
Process pname;
UInt32 INFINITE= 0xFFFFFFFF;
Int32 PAGE_EXECUTE_READWRITE = 0x40;
Int32 MEM_COMMIT= 0x1000;
Int32 MEM_RESERVE= 0x2000;
Int32 MEM_RELEASE= 0x8000;
Int32 AllocBaseAddress;
IntPtr hwnd;
string dllname;
Int32 Pid;
Boolean ok;
Int32 loadaddr;
IntPtr ThreadHwnd;
public Form1()
{
InitializeComponent();
}
UInt32 INFINITE= 0xFFFFFFFF;
Int32 PAGE_EXECUTE_READWRITE = 0x40;
Int32 MEM_COMMIT= 0x1000;
Int32 MEM_RESERVE= 0x2000;
Int32 MEM_RELEASE= 0x8000;
Int32 AllocBaseAddress;
IntPtr hwnd;
string dllname;
Int32 Pid;
Boolean ok;
Int32 loadaddr;
IntPtr ThreadHwnd;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (textBox1.Text == "" || textBox1.Text == null)
{
MessageBox.Show("Pid is null"); return;
}
if (textBox2.Text == "" || textBox2.Text == null)
{
MessageBox.Show("dll name is null"); return;
}
Pid = Int32.Parse(textBox1.Text);
dllname = textBox2.Text;
}
catch(Exception error)
{
MessageBox.Show(error.Message); return;
}
try
{
pname = Process.GetProcessById(Pid);
hwnd = pname.Handle;
}
catch(Exception error)
{ //當標示pid的程式不存在時發生異常;
MessageBox.Show (error.Message); return;
}
AllocBaseAddress= VirtualAllocEx(hwnd, 0, dllname.Length + 1, MEM_COMMIT+ MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (AllocBaseAddress == 0)
{
MessageBox.Show("virtualallocex fail"); return;
}
ok=WriteProcessMemory(hwnd, AllocBaseAddress, dllname, dllname.Length + 1,0);
if (!ok)
{
MessageBox.Show("writeprocessmemory fail"); return;
}
loadaddr = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
if (loadaddr == 0)
{ //取得LoadLibraryA的地址失敗時返回
MessageBox.Show("get loadlibraryA fail"); return;
}
ThreadHwnd=CreateRemoteThread(hwnd, 0, 0, loadaddr, AllocBaseAddress,0, 0);
if (ThreadHwnd ==IntPtr.Zero)
{
MessageBox.Show("createremotethread fail"); return;
}
MessageBox.Show("ok ,you can check now!!!");
WaitForSingleObject(ThreadHwnd, INFINITE);
VirtualFree(hwnd, 0, MEM_RELEASE);
//下面開始列舉模組列表;
ProcessModuleCollection pmodule = pname.Modules;
foreach (ProcessModule processm in pmodule)
{
listBox1.Items.Add(processm.FileName);
}
pname.Dispose();
}
}
}
{
try
{
if (textBox1.Text == "" || textBox1.Text == null)
{
MessageBox.Show("Pid is null"); return;
}
if (textBox2.Text == "" || textBox2.Text == null)
{
MessageBox.Show("dll name is null"); return;
}
Pid = Int32.Parse(textBox1.Text);
dllname = textBox2.Text;
}
catch(Exception error)
{
MessageBox.Show(error.Message); return;
}
try
{
pname = Process.GetProcessById(Pid);
hwnd = pname.Handle;
}
catch(Exception error)
{ //當標示pid的程式不存在時發生異常;
MessageBox.Show (error.Message); return;
}
AllocBaseAddress= VirtualAllocEx(hwnd, 0, dllname.Length + 1, MEM_COMMIT+ MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (AllocBaseAddress == 0)
{
MessageBox.Show("virtualallocex fail"); return;
}
ok=WriteProcessMemory(hwnd, AllocBaseAddress, dllname, dllname.Length + 1,0);
if (!ok)
{
MessageBox.Show("writeprocessmemory fail"); return;
}
loadaddr = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
if (loadaddr == 0)
{ //取得LoadLibraryA的地址失敗時返回
MessageBox.Show("get loadlibraryA fail"); return;
}
ThreadHwnd=CreateRemoteThread(hwnd, 0, 0, loadaddr, AllocBaseAddress,0, 0);
if (ThreadHwnd ==IntPtr.Zero)
{
MessageBox.Show("createremotethread fail"); return;
}
MessageBox.Show("ok ,you can check now!!!");
WaitForSingleObject(ThreadHwnd, INFINITE);
VirtualFree(hwnd, 0, MEM_RELEASE);
//下面開始列舉模組列表;
ProcessModuleCollection pmodule = pname.Modules;
foreach (ProcessModule processm in pmodule)
{
listBox1.Items.Add(processm.FileName);
}
pname.Dispose();
}
}
}
可以看到dll注入是很簡單的,用了很短的程式碼就完成了所有的功能,也可以看到我沒有用到OpenProcess函式,而是用了process類,這個在vb,vc++中是沒有這麼方便的,他們要得到程式的控制程式碼,就要用到OpenProcess函式,關於dll的編寫,我用的只是新建的一個類庫,由於不知道c#有沒有dll入口函式,我開始用main()當入口點,但是好像不起作用,建議dll用vc++編寫,因為c++有dllmain入口函式,可以取得很好的執行。
希望本文對剛剛踏進c#程式設計大門的程式設計愛好者有所幫助,由於本身水平有限,要是文章有什麼不對的地方,希望能夠諒解。
相關文章
- 技術分享 | DLL注入之遠執行緒注入執行緒
- 程式注入之DLL注入
- [原創]注入技術系列:一個批量驗證DLL劫持的工具
- [原創]注入技術系列:一個批次驗證DLL劫持的工具
- COM 程式注入技術
- IOC注入技術之編譯時注入編譯
- 8 - DLL注入和解除安裝
- C# 生成DLL 並 呼叫C#
- C++ DLL注入工具完整原始碼C++原始碼
- Windows提權實戰————4、DLL注入Windows
- [原創]一種通用DLL劫持技術研究
- 使用微軟Detours庫進行DLL注入微軟
- Windows訊息鉤取(簡單DLL注入)Windows
- C#呼叫 C++的DLLC#C++
- 最新堆疊查詢注入攻擊和注入程式碼分析技術
- Android技術棧(三)依賴注入技術的探討與實現Android依賴注入
- 遠端執行緒注入dll,突破session 0執行緒Session
- C# 程式修改dll引用路徑C#
- C++呼叫 c#生成的dllC++C#
- 技術卡片 - 限制依賴注入的數量依賴注入
- PHP phar:協議物件注入技術介紹PHP協議物件
- C# 依賴注入 & MEFC#依賴注入
- 如何掌握C#的核心技術C#
- C# 跨平臺UI 技術C#UI
- DLL解除安裝(建立遠端執行緒解除安裝強制注入的dll)執行緒
- C#配置程式引用的dll的位置C#
- Java agent技術的注入利用與避坑點Java
- 遠端執行緒注入DLL突破session 0 隔離執行緒Session
- Android so注入(inject)和Hook技術學習(二)——GAndroidHook
- 針對新型程式注入技術Ctrl-Inject原理分析
- C++呼叫C#的動態庫dllC++C#
- 最新Base64注入攻擊和程式碼分析技術
- 最新二次注入攻擊和程式碼分析技術
- 最新寬位元組注入攻擊和程式碼分析技術
- AI 技術如何為線上餐飲注入新動能AI
- c#呼叫C++DLL EntryPointNotFoundException 找不到入口點C#C++Exception
- 【IDL】 IDL與C#混合程式設計技術C#程式設計
- C#中的幾個簡單技術點C#
- 使用DLL注入繞過“受控制的資料夾訪問”功能