DLL注入(AppInit_DLLs)

DLL注入(AppInit_DLLs)

一:概述

利用注册表进行dll注入,Windows操作系统的注册表默认是提供了AppInit_DLLs和LoadAppInit_DLLs两个注册表项的。打开我们的注册表编辑器,将要注入的DLL的路径字符串写入到AppInit_DLLs项目,然后将LoadAppInit_DLLs的项目值设置为1。重启后,我们指定路径的dll便会注入到User32.dll的进程(其实基本上就是全部进程了)。实际上就是当User32.dll被加载到进程的时候,会读取AppInit_DLLs注册表项,若有值,则调用LoadLibrary()API加载dll。

二:myhack.dll源码使用到的函数等

备注: 查看myhack.dll的源码时可对照这里

1. DLLMain:

函数原型:

1

2

3

4

5

BOOL WINAPI DllMain(

HINSTANCE hinstDLL, // 指向自身的句柄

DWORD fdwReason, // 调用原因

LPVOID lpvReserved // 隐式加载和显式加载

);

静态链接时,或动态链接时调用LoadLibrary和FreeLibrary都会调用DllMain函数。DllMain的第二个参数fdwReason指明了系统调用Dll的原因,它可能是:

DLL_PROCESS_ATTACH、

DLL_PROCESS_DETACH、

DLL_THREAD_ATTACH、

DLL_THREAD_DETACH。

进程映射

DLL_PROCESS_ATTACH

大家都知道,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary或者LoadLibraryEx。

当一个DLL文件被映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的fdwReason参数为DLL_PROCESS_ATTACH,这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不同进程用LoadLibrary同一个DLL时,每个进程的第一次映射都会用DLL_PROCESS_ATTACH调用DLL的DllMain函数。

可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数。

进程卸载

DLL_PROCESS_DETACH

当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时,它应该执行进程相关的清理工作。

那么什么时候DLL被从进程的地址空间解除映射呢?两种情况:

◆FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)

◆进程结束而解除DLL映射,在进程结束前还没有解除DLL的映射,进程结束后会解除DLL映射。(如果进程的终结是因为调用了TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL在进程结束前没有机会执行任何清理工作。)

注意:当用DLL_PROCESS_ATTACH调用DLL的DllMain函数时,如果返回FALSE,说明没有初始化成功,系统仍会用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须确保清理那些没有成功初始化的东西。

可参考DllMainTest的DLL_PROCESS_DETACH_Test函数。

线程映射

DLL_THREAD_ATTACH

当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。

新创建的线程负责执行这次的DLL的DllMain函数,只有当所有的DLL都处理完这一通知后,系统才允许进程开始执行它的线程函数。

注意跟DLL_PROCESS_ATTACH的区别,我们在前面说过,第n(n>=2)次以后地把DLL映像文件映射到进程的地址空间时,是不再用DLL_PROCESS_ATTACH调用DllMain的。而DLL_THREAD_ATTACH不同,进程中的每次建立线程,都会用值DLL_THREAD_ATTACH调用DllMain函数,哪怕是线程中建立线程也一样。

线程卸载

DLL_THREAD_DETACH

如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。

注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。

2. STARTUPINFO

STARTUPINFO用于指定新进程的主窗口特性的一个结构

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

typedef struct _STARTUPINFO {

DWORD cb;

LPTSTR lpReserved;

LPTSTR lpDesktop;

LPTSTR lpTitle;

DWORD dwX;

DWORD dwY;

DWORD dwXSize;

DWORD dwYSize;

DWORD dwXCountChars;

DWORD dwYCountChars;

DWORD dwFillAttribute;

DWORD dwFlags;

WORD wShowWindow;

WORD cbReserved2;

LPBYTE lpReserved2;

HANDLE hStdInput;

HANDLE hStdOutput;

HANDLE hStdError;

} STARTUPINFO, *LPSTARTUPINFO;

参数说明:

STARTUPINFO结构 该结构用于指定新进程的主窗口特性

DWORD cb; //包含STARTUPINFO结构中的字节数.如果Microsoft将来扩展该结构,它可用作版本控制手段,应用程序必须将cb初始化为sizeof(STARTUPINFO)。

LPSTR lpReserved; //保留。必须初始化为NULL。

LPSTR lpDesktop; //用于标识启动应用程序所在的桌面的名字。如果该桌面存在,新进程便与指定的桌面相关联。如果桌面不存在,便创建一个带有默认属性的桌面,并使用为新进程指定的名字。如果lpDesktop是NULL(这是最常见的情况),那么该进程将与当前桌面相关联。

LPSTR lpTitle; //用于设定控制台窗口的名称。如果lpTitle是NULL,则可执行文件的名字将用作窗口名

DWORD dwX; //用于设定应用程序窗口在屏幕上应该放置的位置的x和y坐标(以像素为单位)。

DWORD dwY; 只有当子进程用CW_USEDEFAULT作为CreateWindow的x参数来创建它的第一个重叠窗口时,

才使用这两个坐标。若是创建控制台窗口的应用程序,这些成员用于指明控制台窗口的左上角

DWORD dwXSize; //用于设定应用程序窗口的宽度和长度(以像素为单位)只有dwYsize

DWORD dwYSize; 当子进程将CW_USEDEFAULT用作CreateWindow的nWidth参数来创建它的第一个重叠窗口时,才使用这些值。

DWORD dwXCountChars; //用于设定子应用程序的控制台窗口的宽度和高度(以字符为单位)

DWORD dwYCountChars;

DWORD dwFillAttribute; //用于设定子应用程序的控制台窗口使用的文本和背景颜色

DWORD dwFlags; //请参见下一段和表4 - 7 的说明

WORD wShowWindow; //用于设定如果子应用程序初次调用的ShowWindow将SW_SHOWDEFAULT作为nCmdShow参数传递时,该应用程序的第一个重叠窗口应该如何出现。

本成员可以是通常用于ShowWindow 函数的任何一个SW _ *标识符

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

**ShowWindow函数:

ShowWindow(

  hWnd: HWND;       {要显示的窗口的句柄}

  nCmdShow: Integer {选项, 参加下表}

): BOOL;

//uCmdShow 参数可选值:

SW_HIDE            = 0;  {隐藏, 并且任务栏也没有最小化图标}

SW_SHOWNORMAL      = 1;  {用最近的大小和位置显示, 激活}

SW_NORMAL          = 1;  {同 SW_SHOWNORMAL}

SW_SHOWMINIMIZED   = 2;  {最小化, 激活}

SW_SHOWMAXIMIZED   = 3;  {最大化, 激活}

SW_MAXIMIZE        = 3;  {同 SW_SHOWMAXIMIZED}

SW_SHOWNOACTIVATE  = 4;  {用最近的大小和位置显示, 不激活}

SW_SHOW            = 5;  {同 SW_SHOWNORMAL}

SW_MINIMIZE        = 6;  {最小化, 不激活}

SW_SHOWMINNOACTIVE = 7;  {同 SW_MINIMIZE}

SW_SHOWNA          = 8;  {同 SW_SHOWNOACTIVATE}

SW_RESTORE         = 9;  {同 SW_SHOWNORMAL}

SW_SHOWDEFAULT     = 10; {同 SW_SHOWNORMAL}

SW_MAX             = 10; {同 SW_SHOWNORMAL}**

WORD cbReserved2; //保留。必须被初始化为0

PBYTE lpReserved2; //保留。必须被初始化为NULL

HANDLE hStdInput; //用于设定供控制台输入和输出用的缓存的句柄。按照默认设置,hStdInput用于标识键盘缓存,hStdOutput和hStdError用于标识控制台窗口的缓存

HANDLE hStdOutput;

HANDLE hStdError;

当Windows创建新进程时,它将使用该结构的有关成员。大多数应用程序将要求生成的应用程序仅仅使用默认值。至少应该将该结构中的所有成员初始化为零,然后将cb成员设置为该结构的大小:

STARTUPINFO si = { sizeof(si) };

CreateProcess(...,&si,...);

表4-7 dwFlags 使用标志及含义

标志 含义

STARTF_USESIZE // 使用dwXSize和dwYSize成员

STARTF_USESHOWWINDOW //使用wShowWindow成员

STARTF_USEPOSITION //使用dwX和dwY成员

STARTF_USECOUNTCHARS //使用dwXCountChars和dwYCountChars成员

STARTF_USEFILLATTRIBUTE //使用dwFillAttribute成员

STARTF_USESTDHANDLES //使用hStdInput、hStdOutput和hStdError成员

STARTF_RUN_FULLSCREEN //强制在x 8 6 计算机上运行的控制台应用程序以全屏幕方式启动运行

另外还有两个标志,即STARTF_FORCEONFEEDBACK和STARTF_+FORCEOFFF -EEDBACK ,当启动一个新进程时,它们可以用来控制鼠标的光标。由于Windows支持真正的多任务抢占式运行方式,因此可以启动一个应用程序,然后在进程初始化时,使用另一个程序。为了向用户提供直观的反馈信息,C r e a t e P r o c e s s 能够临时将系统的箭头光标改为一个新光标,即沙漏箭头光标:

该光标表示可以等待出现某种情况,也可以继续使用系统。当启动另一个进程时,CreateProcess函数使你能够更好地控制光标。当设定STARTF_FORCEONFEEDBACK标志时,C r e a t e P r o c e s s 并不将光标改为沙漏。

STARTF_FORCEONFEEDBACK可使CreateProcess能够监控新进程的初始化,并可根据结果来改变光标。当使用该标志来调用CreateProcess时,光标改为沙漏。过2 s 后,如果新进程没有调用G U I ,CreateProcess 将光标恢复为箭头。

如果该进程在2 s 内调用了GUI ,CreateProcess将等待该应用程序显示一个窗口。这必须在进程调用G U I 后5 s内发生。如果没有显示窗口,CreateProcess就会恢复原来的光标。如果显示了一个窗口,CreateProcess将使沙漏光标继续保留5s 。如果某个时候该应用程序调用了G e t M e s s a g e 函数,指明它完成了初始化,那么C r e a t e P r o ce s s 就会立即恢复原来的光标,并且停止监控新进程。

在结束这一节内容的介绍之前,我想讲一讲S TA RT U P I N F O 的w S h o w Wi n d o w成员。你将该成员初始化为传递给( w ) Wi n M a i n 的最后一个参数n C m d S h o w的值。该成员显示你想要传递给新进程的( w ) Wi n M a i n 函数的最后一个参数n C m d S h o w的值。它是可以传递给S h o w Wi n d o w 函数的标识符之一。通常,n C m d S h o w 的值既可以是S W SH O W N O R M A L ,也可以是SW SHOWMINNOACTIVE 。但是,它有时可以是S W _ S H O W D EFA U LT 。

当在E x p l o r e r 中启动一个应用程序时,该应用程序的( w ) Wi n M a i n 函数被调用,而S W _ SH O W N O R M A L 则作为n C m d S h o w参数来传递。如果为该应用程序创建了一个快捷方式,可以使用快捷方式的属性页来告诉系统,应用程序的窗口最初应该如何显示。图4 - 3 显示了运行No t e p a d 的快捷方式的属性页。注意,使用R u n 选项的组合框,就能够设定如何显示N o t e p a d 的窗口。

当使用E x p l o r e r 来启动该快捷方式时,E x p l o r e r 会正确地准备S TA RT U P I N FO 结构并调用C r e a t e P r o c e s s 。这时N o t e p a d 开始运行,并且为n C m d S h ow 参数将S W _ S H O W M I N N O A C T I V E传递给它的( w ) Wi n M a i n 函数。

运用这样的方法,用户能够很容易地启动一个应用程序,其主窗口可以用正常状态、最小或最大状态进行显示。

最后,应用程序可以调用下面的函数,以便获取由父进程初始化的S TA RT U P I N F O 结构的拷贝。子进程可以查看该结构,并根据该结构的成员的值来改变它的行为特性。

VOIDGetStartupInfo(LPSTARTUPINFO pStartupInfo);

注意虽然Wi n d o w s 文档没有明确地说明,但是在调用G e t S t a r t I n f o 函数之前,必须像下面这样对该结构的c b 成员进行初始化:

STARTUPINFO si = { sizeof(si) };

GetStartupInfo(&si);

3. GetModuleFileName

获取当前进程已加载模块的文件的完整路径,该模块必须由当前进程加载。

如果想要获取另一个已加载模块的文件路径,可以使用GetModuleFileNameEx函数。

1

2

3

4

5

6

7

8

9

GetModuleFileName(

HMODULE hModule,

LPTSTR lpFilename,

DWORD nSize

);

hModule Long: 一个模块的句柄。可以是一个DLL模块,或者是一个应用程序的实例句柄。如果该参数为NULL,该函数返回该应用程序全路径。

lpFileName String: 指定一个字串缓冲区,要在其中容纳文件的用NULL字符中止的路径名,hModule模块就是从这个文件装载进来的

nSize Long: 装载到缓冲区lpFileName的最大字符数

返回值:如果返回为成功,将在lpFileName的缓冲区当中返回相应模块的路径,如果所设的nSize过小,那么返回仅按所设置缓冲区大小返回相应字符串内容。如果函数失败,返回值将为0,利用GetLastError可获得异常代码。

4. _tcsrchr和_tcsicmp

_tcsrchr:

查找字符串中某个字符最后一次出现的位置

两个参数

第一个参数:字符串

第二个参数:查找的字符

返回值:指向最后一次在字符串中出现的该字符的指针,如果要查找的字符再串中没有出现,则返回NULL。

_tcsicmp:

不区分大小写比较

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

附常用函数功能简介表:

_tcsclen 大小

_tcscpy 拷贝

_tcscat 加尾

lstrcpyn 带大小拷贝

_tcsicmp stricmp 不区分大小写比较

_tcscmp   区分大小写比较

_tcsnccmp strncmp wcsncmp 区分大小写比较

_ttoi atoi  字母转数字int

_ttol atol  字母转数字long

_tstof atof 字母转数字double

_ltot ltoa long转换成字符

_tcstol wcstol  strtol

_stprintf  格式化

_sntprintf  _snprintf 格式化

_tprintf printf wprintf 输出

_tcsupr  _strupr 大写化

_tcslwr strlwr 小写化

_tcsrchr strrchr 查找最后的字符

_stscanf sscanf 格式化获得数值

5. PROCESS_INFORMATION

在创建进程时相关的数据结构之一,该结构返回有关新进程及其主线程的信息。

1

2

3

4

5

6

typedef struct_PROCESS_INFORMATION{

HANDLE hProcess;

HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;

}PROCESS_INFORMATION;

该结构体成员含义:

① hProcess:返回新进程的句柄。

② hThread:返回主线程的句柄。

③ dwProcessId:返回一个全局进程标识符。该标识符用于标识一个进程。从进程被

创建到终止,该值始终有效。

④ dwThreadId:返回一个全局线程标识符。该标识符用于标识一个线程。从线程被创

建到终止,该值始终有效。

6. CreateProcess

用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//函数原型:

BOOL CreateProcess

(

LPCTSTR lpApplicationName,

LPTSTR lpCommandLine,

LPSECURITY_ATTRIBUTES lpProcessAttributes,

LPSECURITY_ATTRIBUTES lpThreadAttributes,

BOOL bInheritHandles,

DWORD dwCreationFlags,

LPVOID lpEnvironment,

LPCTSTR lpCurrentDirectory,

LPSTARTUPINFO lpStartupInfo,

LPPROCESS_INFORMATIONlpProcessInformation

);

参数:

pApplicationName

指向一个NULL结尾的、用来指定可执行模块的字符串。

这个字符串可以是可执行模块的绝对路径,也可以是相对路径,在后一种情况下,函数使用当前驱动器和目录建立可执行模块的路径。

这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于 lpCommandLine 参数最前面并由空格符与后面的字符分开。

lpCommandLine

指向一个以NULL结尾的字符串,该字符串指定要执行的命令行。

这个参数可以为空,那么函数将使用lpApplicationName参数指定的字符串当做要运行的程序的命令行。

如果lpApplicationName和lpCommandLine参数都不为空,那么lpApplicationName参数指定将要被运行的模块,lpCommandLine参数`指定将被运行的模块的命令行。新运行的进程可以使用GetCommandLine函数获得整个命令行。C语言程序可以使用argc和argv参数。

lpProcessAttributes

指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。

在Windows NT中:SECURITY_ATTRIBUTES结构的lpSecurityDescriptor成员指定了新进程的安全描述符,如果参数为空,新进程使用默认的安全描述符。

lpThreadAttributes

同lpProcessAttribute,不过这个参数决定的是线程是否被继承.通常置为NULL.

bInheritHandles

指示新进程是否从调用进程处继承了句柄。

如果参数的值为真,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限。

dwCreationFlags

指定附加的、用来控制优先类和进程的创建的标志。以下的创建标志可以以除下面列出的方式外的任何方式组合后指定。

⑴值:CREATE_DEFAULT_ERROR_MODE

含义:新的进程不继承调用进程的错误模式。CreateProcess函数赋予新进程当前的默认错误模式作为替代。应用程序可以调用SetErrorMode函数设置当前的默认错误模式。

这个标志对于那些运行在没有硬件错误环境下的多线程外壳程序是十分有用的。

对于CreateProcess函数,默认的行为是为新进程继承调用者的错误模式。设置这个标志以改变默认的处理方式。

⑵值:CREATE_NEW_CONSOLE

含义:新的进程将使用一个新的控制台,而不是继承父进程的控制台。这个标志不能与DETACHED_PROCESS标志一起使用。

⑶值:CREATE_NEW_PROCESS_GROUP

含义:新进程将是一个进程树的根进程。进程树中的全部进程都是根进程的子进程。新进程树的用户标识符与这个进程的标识符是相同的,由lpProcessInformation参数返回。进程树经常使用GenerateConsoleCtrlEvent函数允许发送CTRL+C或CTRL+BREAK信号到一组控制台进程。

⑷值:CREATE_SEPARATE_WOW_VDM

如果被设置,新进程将会在一个私有的虚拟DOS机(VDM)中运行。另外,默认情况下所有的16位Windows应用程序都会在同一个共享的VDM中以线程的方式运行。单独运行一个16位程序的优点是一个应用程序的崩溃只会结束这一个VDM的运行;其他那些在不同VDM中运行的程序会继续正常的运行。同样的,在不同VDM中运行的16位Windows应用程序拥有不同的输入队列,这意味着如果一个程序暂时失去响应,在独立的VDM中的应用程序能够继续获得输入。

⑸值:CREATE_SHARED_WOW_VDM

如果WIN.INI中的Windows段的DefaultSeparateVDM选项被设置为真,这个标识使得CreateProcess函数越过这个选项并在共享的虚拟DOS机中运行新进程。

⑹值:CREATE_SUSPENDED

含义:新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。

⑺值:CREATE_UNICODE_ENVIRONMENT

含义:如果被设置,由lpEnvironment参数指定的环境块使用Unicode字符,如果为空,环境块使用ANSI字符。

⑻值:DEBUG_PROCESS

含义:如果这个标志被设置,调用进程将被当做一个调试程序,并且新进程会被当做被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。

如果你使用这个标志创建进程,只有调用进程(调用CreateProcess函数的进程)可以调用WaitForDebugEvent函数。

⑼值:DEBUG_ONLY_THIS_PROCESS

含义:如果此标志没有被设置且调用进程正在被调试,新进程将成为调试调用进程的调试器的另一个调试对象。如果调用进程没有被调试,有关调试的行为就不会产生。

⑽值:DETACHED_PROCESS

含义:对于控制台进程,新进程没有访问父进程控制台的权限。新进程可以通过AllocConsole函数自己创建一个新的控制台。这个标志不可以与CREATE_NEW_CONSOLE标志一起使用。

〔11〕值:CREATE_NO_WINDOW

含义:系统不为新进程创建CUI窗口,使用该标志可以创建不含窗口的CUI程序。

dwCreationFlags参数

还用来控制新进程的优先类,优先类用来决定此进程的线程调度的优先级。如果下面的优先级类标志都没有被指定,那么默认的优先类是NORMAL_PRIORITY_CLASS,除非被创建的进程是IDLE_PRIORITY_CLASS。在这种情况下子进程的默认优先类是IDLE_PRIORITY_CLASS

可以选择下面的标志中的一个:

优先级:HIGH_PRIORITY_CLASS

含义:指示这个进程将执行时间临界的任务,所以它必须被立即运行以保证正确。这个优先级的程序优先于正常优先级或空闲优先级的程序。一个例子是Windows任务列表,为了保证当用户调用时可以立刻响应,放弃了对系统负荷的考虑。确保在使用高优先级时应该足够谨慎,因为一个高优先级的CPU关联应用程序可以占用几乎全部的CPU可用时间。

优先级:IDLE_PRIORITY_CLASS

含义:指示这个进程的线程只有在系统空闲时才会运行并且可以被任何高优先级的任务打断。例如屏幕保护程序。空闲优先级会被子进程继承。

优先级:NORMAL_PRIORITY_CLASS

含义:指示这个进程没有特殊的任务调度要求。

优先级:REALTIME_PRIORITY_CLASS

含义:指示这个进程拥有可用的最高优先级。一个拥有实时优先级的进程的线程可以打断所有其他进程线程的执行,包括正在执行重要任务的系统进程。例如,一个执行时间稍长一点的实时进程可能导致磁盘缓存不足或鼠标反映迟钝。

lpEnvironment

指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境。

一个环境块存在于一个由以NULL结尾的字符串组成的块中,这个块也是以NULL结尾的。每个字符串都是name=value的形式。

因为相等标志被当做分隔符,所以它不能被环境变量当做变量名。

与其使用应用程序提供的环境块,不如直接把这个参数设为空,系统驱动器上的当前目录信息不会被自动传递给新创建的进程。对于这个情况的探讨和如何处理,请参见注释一节。

环境块可以包含Unicode或ANSI字符。如果lpEnvironment指向的环境块包含Unicode字符,那么dwCreationFlags字段的CREATE_UNICODE_ENⅥRONMENT标志将被设置。如果块包含ANSI字符,该标志将被清空。

请注意一个ANSI环境块是由两个零字节结束的:一个是字符串的结尾,另一个用来结束这个快。一个Unicode环境块是由四个零字节结束的:两个代表字符串结束,另两个用来结束块。

lpCurrentDirectory

指向一个以NULL结尾的字符串,这个字符串用来指定子进程的工作路径。这个字符串必须是一个包含驱动器名的绝对路径。如果这个参数为空,新进程将使用与调用进程相同的驱动器和目录。这个选项是一个需要启动应用程序并指定它们的驱动器和工作目录的外壳程序的主要条件。

lpStartupInfo

指向一个用于决定新进程的主窗体如何显示的STARTUPINFO结构体。

lpProcessInformation

指向一个用来接收新进程的识别信息的PROCESS_INFORMATION结构体。

返回值

如果函数执行成功,返回非零值。

如果函数执行失败,返回零,可以使用GetLastError函数获得错误的附加信息。

三:myhack.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

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

// myhack.cpp. 作用是以隐藏模式运行IE,连接到指定网站

#include "windows.h"

#include "tchar.h"

#define DEF_CMD  L"c:\\Program Files\\Internet Explorer\\iexplore.exe"  //定义要打开的浏览器的路径

#define DEF_ADDR L"http://www.naver.com"  //要打开的网址

#define DEF_DST_PROC L"notepad.exe"       //要用于比较的进程的名称

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

{

    TCHAR szCmd[MAX_PATH]  = {0,};

    TCHAR szPath[MAX_PATH] = {0,};

    TCHAR *= NULL;

    STARTUPINFO si = {0,};    //定义一个STARTUPINFO类型的结构体,用于指定新进程的主窗口特性的一个结构

    PROCESS_INFORMATION pi = {0,}; //定义一个PROCESS_INFORMATION类型的结构体, 在创建进程时相关的数据结构之一,返回有关新进程及其主线程的信息。

    si.cb = sizeof(STARTUPINFO);     //包含STARTUPINFO结构中的字节数

    si.dwFlags = STARTF_USESHOWWINDOW; //使用该结构体的wShowWindow成员

    si.wShowWindow = SW_HIDE; //以隐藏方式打开窗口,即隐藏, 并且任务栏也没有最小化图标

    switch( fdwReason )

    {

    case DLL_PROCESS_ATTACH :

        if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) //获取该dll加载到的进程的全路径

            break;

        if( !(p = _tcsrchr(szPath, '\\')) ) //获取"\\"字符之后的进程名指针

            break;

        if( _tcsicmp(p+1, DEF_DST_PROC) )  //比较进程是否相同

            break;

        wsprintf(szCmd, L"%s %s", DEF_CMD, DEF_ADDR);  //将浏览器地址和网址格式化打印到szCmd数组中

        if( !CreateProcess(NULL, (LPTSTR)(LPCTSTR)szCmd,

                            NULL, NULL, FALSE,

                            NORMAL_PRIORITY_CLASS,

                            NULL, NULL, &si, &pi) ) //创建进程,第二个参数用于指向一个以NULL结尾的字符串,该字符串指定要执行的命令行。

            break;         //FALSE表示新进程没有从调用进程处继承了句柄。

        if( pi.hProcess != NULL )   //pi.hProcess返回新进程的句柄

            CloseHandle(pi.hProcess);

        break;

    }

    return TRUE;

}

四:练习myhack.dll

  1. 复制myhack.dll的全路径(最好都是英文路径)
  2. 修改注册表项:

将AppInit_DLLs的值设为要注入的dll的路径:


将LoadAppInitDLLs的值改为1:

然后重启系统(注:重启后才能将该dll注入进User32.dll的全部进程中)
 


进程名不匹配的进程,该dll注入了也不会发生什么作用(dll源码中有个_tcsicmp),只有当进程名匹配的时候才会调用CreateProcess。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/487123.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot + Spring AI快速体验

Spring AI快速体验 1 什么是Spring AI主要功能 2 快速开始2.1 版本说明2.2 配置文件2.3 pom依赖2.3.1 spring maven仓库2.3.2 核心依赖 2.4 定义ChatClient2.5 启动类2.6 测试 3 参考链接 1 什么是Spring AI Spring AI是Spring的一个子项目,是Spring专门面向于AI的…

算法基础学习Day5(双指针、动态窗口)

文章目录 1.题目2.题目解答1.四数之和题目及题目解析算法学习代码提交 2.长度最小的子数组题目及题目解析滑动窗口的算法学习方法一:单向双指针(暴力解法)方法二:同向双指针(滑动窗口) 代码提交 1.题目 18. 四数之和 - 力扣(LeetCode&#x…

通义千问sft-甄嬛对话

流程步骤 https://www.datawhale.cn/activity/110/21/76?rankingPage1 按照上面的流程,准备好数据之后就可以直接对7b的模型进行指令微调了,整个流程不是很复杂,操作起来比较方便。但是发布服务等了较长时间,以为出了bug 结果展…

1-6 ESP32控制LED灯

1.0 LED简介 LED是英文 "Light Emitting Diode" 的缩写,中文翻译为发光二极管。它是一种能够将电能转化为光能的电子元件。LED是一种半导体器件,在通电时会发出可见光。和传统的白炽灯泡或荧光灯相比,LED具有诸多优点:高…

前端成长之路:HTML(1)

每个网页都会有一个基本的结构标签&#xff08;也称为骨架标签&#xff09;&#xff0c;页面内容也是在这些基本标签上书写。 基本结构标签&#xff08;骨架标签&#xff09; <html></html>标签是HTML标签&#xff0c;是页面中最大的标签&#xff0c;被称为根标签…

细说敏捷:敏捷四会之回顾会

在前面的分享中&#xff0c;我们已经梳理了计划会、每日站会和复盘会的召开要点&#xff0c;本篇我们再对Scrum敏捷四大仪式中的最后一个会议仪式 - 迭代回顾会 进行探讨 回顾会的目的和作用 回顾会因为和复盘会一般都放在迭代的最后一天&#xff0c;而且通常安排是相邻在一起…

重生之我在异世界学智力题(1)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言智力题题目&#xff1a;《奇怪的时钟…

【模型对比】ChatGPT vs Kimi vs 文心一言那个更好用?数据详细解析,找出最适合你的AI辅助工具!

在这个人工智能迅猛发展的时代&#xff0c;AI聊天助手已经深入我们的工作与生活。你是否曾在选择使用ChatGPT、Kimi或是百度的文心一言时感到一头雾水&#xff1f;每款AI都有其独特的魅力与优势&#xff0c;那么&#xff0c;究竟哪一款AI聊天助手最适合你呢&#xff1f;本文将带…

【时时三省】(C语言基础)结构体内存对齐练习题

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 练习一 这个输出结果是8 练习二 这个输出结果是16 练习三 这个输出结果是32 上面的输出结果都是根据结构体对齐规则来计算的

【python】UTF-8编码

# -*- coding: utf-8 -*-import sys reload(sys) # This reloads the system default encoding setup sys.setdefaultencoding(utf-8) # Set the default encoding to utf-8 print(sys.getdefaultencoding())写在最后&#xff1a;若本文章对您有帮助&#xff0c;请点个赞啦 ٩…

MySQL 性能优化详解

MySQL 性能优化详解 硬件升级系统配置优化调整buffer_pool数据预热降低日志的磁盘落盘 表结构设计优化SQL语句及索引优化SQL优化实战案例 MySQL性能优化我们可以从以下四个维度考虑&#xff1a;硬件升级、系统配置、表结构设计、SQL语句和索引。 从成本上来说&#xff1a;硬件升…

PCB设计规范

过孔设计 过孔盖油工艺&#xff08;也成为连塞带印&#xff09;&#xff1a;常规工艺、免费工艺&#xff0c;无特殊情况也建议使用此工艺。过孔大小建议直径在0.3mm-0.5mm之间。最省钱&#xff0c;效果最好。 非金属化槽孔 PCB制造商在加工非金属化槽孔时通常采用锣刀加工。最…

MVC基础——市场管理系统(二)

文章目录 项目地址三、Produtcts的CRUD3.1 Products列表的展示页面(Read)3.1.1 给Product的Model里添加Category的属性3.1.2 View视图里展示Product List3.2 增加Product数据(Add)3.2.1 创建ViewModel用来组合多个Model3.2.2 在_ViewImposts里引入ViewModels3.2.3 添加Add的…

vivado中,generate output product 和Create HDL wrapper的作用

generate output product 以zynq的ip核举例&#xff0c;没有generate output product之前&#xff0c;在ip source 什么也看不到。 但是同样的一个ip核&#xff0c;generate output product之后&#xff0c;会生成综合&#xff0c;布线和仿真文件&#xff0c;约束文件等等。 …

uni-app 组成和跨端原理 【跨端开发系列】

&#x1f517; uniapp 跨端开发系列文章&#xff1a;&#x1f380;&#x1f380;&#x1f380; uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…

双目相机的标定,视差图,深度图,点云生成思路与实现。

该文档记录从双目相机标定到点云生成的所有过程&#xff0c;同时会附上代码。 代码直接能跑。https://github.com/stu-yzZ/stereoCamera 目录 大致思路如下&#xff1a; 一、相机标定 1、相机参数介绍 2、单目相机标定 3、双目相机标定 二、图片畸变矫正 三、极线矫正…

Selenium:强大的 Web 自动化测试工具

Selenium&#xff1a;强大的 Web 自动化测试工具 在当今的软件开发和测试领域&#xff0c;自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具&#xff0c;它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么&#xff0c…

基于 Spring Boot + Vue 的宠物领养系统设计与实现

引言 近年来&#xff0c;随着人们生活水平的提高&#xff0c;宠物逐渐成为许多家庭的重要成员。然而&#xff0c;宠物的流浪和弃养问题日益严重&#xff0c;这促使社会对宠物领养的需求不断增长。为解决宠物领养中信息不对称、领养流程复杂等问题&#xff0c;设计并实现一个基…

佑驾创新冲刺上市:交付进度延后,研发投入缩减,刘国清为实控人

近日&#xff0c;深圳佑驾创新科技股份有限公司&#xff08;MINIEYE&#xff0c;下称“佑驾创新”&#xff09;通过港交所聆讯并披露了聆讯后资料集&#xff08;即招股书&#xff09;。据贝多财经了解&#xff0c;佑驾创新获得了IPO备案通知书&#xff0c;拟在港交所上市。 对…

JS中的原型链与继承

原型链的类比 JS中原型链&#xff0c;本质上就是对象之间的关系&#xff0c;通过protoype和[[Prototype]]属性建立起来的连接。这种链条是动态的&#xff0c;可以随时变更。 这个就跟C/C中通过指针建立的关系很相似&#xff0c;比如&#xff0c;通过指针建立一个链表&#xf…