ฉันใช้เวลาช่วงบ่ายพลิกผ่าน MSDN และเขียนตัวอย่างนี้
ฉันเขียน testdll.dll ซึ่งมีฟังก์ชั่นบันทึกเท่านั้นซึ่งใช้ในการส่งออกข้อมูลในไฟล์ test.txt
สภาพแวดล้อมการทดสอบ: WindowsServer2003+Delphi7.0
โปรแกรมนี้ง่ายมากดังนั้นผู้เชี่ยวชาญไม่จำเป็นต้องอ่าน
testdll.dll ซอร์สโค้ดสำหรับการทดสอบ (จะถูกฉีดลงใน prjzzhost.exe):
รหัสโปรแกรมLibrarytestdll;
ใช้
Sysutils
ระบบ,
หน้าต่าง
ชั้นเรียน;
Processurelog (S: PCHAR); stdcall;
วาจา
F: TextFile;
เริ่ม
กำหนด (f, 'test.txt');
iffileexists ('test.txt') append (f)
Elserewrite (F);
writeeln (f, s);
ปิดไฟล์ (f);
จบ;
ProcedureDlLentryPoint (DWREASON: DWORD);
เริ่ม
casedwressorof
dll_process_attach:
บันทึก ('dllprocessattach');
dll_process_detach:
log ('dllprocessdetach');
dll_thread_attach:
บันทึก ('dllthreadattach');
dll_thread_detach:
log ('dllthreaddetach');
จบ;
จบ;
การส่งออก
บันทึก;
เริ่ม
dllproc: =@dllentrypoint;
dllentrypoint (dll_process_attach);
จบ.
กระบวนการโฮสต์ที่ฉีด prjzzhost.exe (ไม่ทำอะไรเลยมันไร้เดียงสามาก :) ฉันจะไม่ให้รหัสที่นี่เพราะมันง่ายเกินไปฮ่าฮ่า
ในที่สุดสิ่งที่สำคัญที่สุดคือ:
ซอร์สโค้ดของ Project1.exe:
รหัสโปรแกรมUNITUNIT1;
ส่วนต่อประสาน
ใช้
Windows, ข้อความ, sysutils, ตัวแปร, คลาส, กราฟิก, การควบคุม, รูปแบบ,
กล่องโต้ตอบ, stdctrls, tlhelp32;
พิมพ์
tlog = ขั้นตอน (s: pchar); stdcall;
tservicemain = ขั้นตอน (argc: จำนวนเต็ม; varargv: pchar); stdcall;
edllloaderror = คลาส (ข้อยกเว้น);
tform1 = คลาส (tform)
ปุ่ม 3: tbutton;
ProcedureButton3Click (ผู้ส่ง: tobject);
ส่วนตัว
{privatedeclarations}
สาธารณะ
{PublicDeclarations}
จบ;
วาจา
Form1: TFORM1;
การดำเนินการ
{$ r*.dfm}
{การลงทะเบียนของกระบวนการ}
ProcedureGetMyProcessId (constafilename: String; constpathMatch: boolean; varprocessId: dword);
วาจา
LPPE: tprocessentry32;
Sshandle: Thandle;
Foundaproc, Foundok: บูลีน;
เริ่ม
processId: = 0;
{สร้างสแน็ปช็อตระบบ}
sshandle: = createToolhelp32snapshot (Th32cs_snapprocess, 0);
{รับกระบวนการแรกใน snapshot}
{ตรวจสอบให้แน่ใจว่าได้ตั้งค่าขนาดของโครงสร้างมิฉะนั้นจะส่งคืน false}
lppe.dwsize: = sizeof (tprocessentry32);
FoundAproc: = process32first (sshandle, lppe);
ขณะที่ Foundaprocdo
เริ่ม
{สร้างการแข่งขัน}
ifpathMatchthen
Foundok: = ansistricomp (lppe.szexefile, pchar (afilename)) = 0
อื่น
Foundok: = ansistricomp (pchar (extractfilename (lppe.szexefile)), pchar (extractfilename (afilename))) = 0;
iffoundokthen
เริ่ม
processId: = lppe.th32processid;
หยุดพัก;
จบ;
{ไม่พบ, ดำเนินการต่อไปยังกระบวนการถัดไป}
FoundAproc: = process32next (sshandle, lppe);
จบ;
ภาพใกล้ชิด (sshandle);
จบ;
{ตั้งค่าสิทธิ์}
functionenabledDebugPrivilege (constenabled: boolean): บูลีน;
วาจา
htk: thandle; {เปิดโทเค็นที่จับ}
rtntemp: dword; {ค่าที่ส่งคืนเมื่อปรับสิทธิ์}
TOKENPRI: TOKEN_PRIVILESS;
const
se_debug = 'sedebugprivilege'; {ค่าการสืบค้น}
เริ่ม
ผลลัพธ์: = เท็จ;
{รับการจัดการโทเค็นกระบวนการตั้งค่าสิทธิ์}
ถ้า (openProcessToken (getCurrentProcess (), token_adjust_privileges, htk)) แล้ว
เริ่ม
tokenpri.privilegeCount: = 1;
{รับค่า luid}
lookupprivilegevalue (nil, se_debug, tokenpri.privileges [0] .luid);
ifenabledthen
tokenpri.privileges [0] .attributes: = se_privilege_enabled
อื่น
tokenpri.privileges [0] .attributes: = 0;
rtntemp: = 0;
{ตั้งค่าสิทธิ์ใหม่}
AdjustTokenPrivileges (HTK, FALSE, TOKENPRI, Sizeof (Tokenpri), Nil, Rtntemp);
ผลลัพธ์: = getLasterRor = error_success;
ภาพใกล้ชิด (HTK);
จบ;
จบ;
{ฟังก์ชั่นการดีบัก}
PromerureOutputText (VARCH: PCHAR);
วาจา
FileHandle: TextFile;
เริ่ม
กำหนดไฟล์ (filehandle, 'zztest.txt');
ผนวก (filehandle);
writeln (filehandle, ch);
Flush (filehandle);
ปิดไฟล์ (filehandle);
จบ;
{ฉีดกระบวนการระยะไกล}
functionInjectTo (consthost, แขก: สตริง; constpid: dword = 0): dword;
วาจา
{มือจับกระบวนการฉีด, รหัสกระบวนการ}
Hremoteprocess: Thandle;
dwremoteprocessid: dword;
{ขนาดของเนื้อหาที่เขียนไปยังกระบวนการระยะไกล}
memsize: dword;
{ที่อยู่หลังจากเขียนไปยังกระบวนการระยะไกล}
pszlibfileremote: ตัวชี้;
IreturnCode: บูลีน;
Tempvar: DWORD;
{ชี้ไปที่ที่อยู่ของฟังก์ชั่น loadlibraryw}
pfnstartaddr: tfnthreadstartroutine;
{เส้นทางเต็ม DLL ต้องเขียนลงในหน่วยความจำของกระบวนการระยะไกล}
pszlibafilename: Pwidechar;
เริ่ม
ผลลัพธ์: = 0;
{ตั้งค่าสิทธิ์}
enableddebugprivilege (จริง);
{จัดสรรขนาดหน่วยความจำสำหรับเส้นทางไฟล์ DLL ที่ฉีดเนื่องจากเป็น wideChar มันจะต้องคูณด้วย 2}
getMem (pszlibafilename, ความยาว (แขก)*2+1);
StringTowideChar (แขก, pszlibafilename, ความยาว (แขก)*2+1);
{รับรหัสกระบวนการ}
ifpid> 0 แล้ว
dwremoteprocessid: = pid
อื่น
getMyProcessID (โฮสต์, เท็จ, dwremoteprocessid);
{รับการจัดการกระบวนการระยะไกลมีสิทธิ์เขียน}
HREMOTEPROCESS: = OpenProcess (process_create_thread+{อนุญาตการสร้างเธรดระยะไกล}
process_vm_operation+{อนุญาตการดำเนินการ VM ระยะไกล}
process_vm_write, {อนุญาตการเขียน VM ระยะไกล}
เท็จ dwremoteprocessid);
{ใช้ฟังก์ชั่น VirtualAlloCex เพื่อจัดสรรพื้นที่ในกระบวนการระยะไกลและเขียนเส้นทาง DLL ใน WriteProcessMemory}
memsize: = (1+lstrlenw (pszlibafilename))*sizeof (wchar);
pszlibfileremote: = pwidestring (virtualallocex (hremoteprocess, nil, memsize, mem_commit, page_readwrite));
Tempvar: = 0;
IreturnCode: = WriteProcessMemory (HremoteProcess, PszLibFileRemote, Pszlibafilename, Memsize, Tempvar);
ifireturncodethen
เริ่ม
pfnstartaddr: = getProcaddress (getModuleHandle ('Kernel32'), 'loadlibraryw');
Tempvar: = 0;
{เริ่ม dll ในกระบวนการระยะไกล}
ผลลัพธ์: = createMotetHread (HREMOTEPROCESS, NIL, 0, PFNSTARTADDR, PSZLIBFILEREMOTE, 0, TempVar);
จบ;
{พื้นที่หน่วยความจำฟรี}
Freemem (pszlibafilename);
จบ;
{ทดสอบ}
ProcedureTform1.button3click (ผู้ส่ง: tobject);
เริ่ม
injectto ('prjzzhost.exe', extractFilePath (paramstr (0))+'testdll.dll');
จบ;
จบ.
รหัสไม่ได้พิจารณาผลที่ตามมาของ DLL ที่ถูกโหลด