• 接触DLL编写并实现线程注入和全局钩子


     资料"<<windows核心编程>> 
    你不会C,那先找本C的书...如果想要电子书的可以回帖留下你的Email,有空发给你,一些 

    自己珍藏的书籍 
    还有你应有VC++6.0和MSDN 
    好了,开始吧 

    目录 
    0一点建议 

    1DLL基本知识 

    2编写我们的DLL 

    3编写加载我们DLL的Loader,实现一个类似RUNDLL32.EXE的程序 

    4线程注入之Loader编写 

    5全局钩子之实现 


    0一点建议 
    书不是重头看到尾,有些书只是用来参考的..所以不要什么书都看...把基础打好,就可以 

    深入去探讨某些问题..不懂的就找资料..查,总结收获,这样学到的知识才是你的 
    这文章很多代码没怎么注释,这样文章感觉会比较长,而且很多解释MSDN和<<windows核心 

    编程>>讲的很好了,就不再重复.,而且讲这些东西很累比如说什么DllMain()和哪个API.. 

    这些别人说的已经足够好了,如果不懂应该先去把基础打好.好了费话到此.. 


    1 DLL基本知识 
    DLLs,函数储存在一个独立的动态链接库文件中。在创建Windows程序时,链接过程并不 

    把DLLs文件链接到程序上。直到程  
    序运行并调用一个DLLs中的函数时,该程序才要求这个函数的地址。此时Windows才在 

    DLLs中寻找被调用函数,并把它的地址传送给调用程序。采用这种方法,DLLs达到了复用 

    代码的极限。  
    DLLs不仅提供了函数重用的机制,而且提供了数据共享的机制。任何应用程序都可以共享 

    由装入内存的DLLs管理的内存资源块。只包含共享数据的DLLs称为资源文件。如Windows 

    的字体文件等 
    2 编写我们的DLL 
    上次在吧里已经有发一个帖说明怎么编写DLL了http://tieba.baidu.com/f?kz=304645377,,不过那是很基本的..现在我们重新再写一个吧...里面有俩个函数,一个是 

    修改系统时间的..,一个是输出你电脑用户名的...就是前些时候我写的哪个 
    好了开始我们的DLL编写,让它导出俩个函数 
    VC++6.0打开->文件->新建->工程->win32 动态连接库-> 工程名我写了sysnap 
    然后一个空的DLL工程,完成 
    接下来就是文件->新建->c++ source 
    开始写代码 
    #include <windows.h> 


    _declspec(dllexport)   void SetTime()  
    {  
     WORD wYear; 
     SYSTEMTIME time;  
      
     printf("想改到哪年:"); 
     scanf("%d",&wYear); 
      
     GetSystemTime(&time);  
     time.wYear = wYear;  
     if (!SetSystemTime(&time))  
     printf("修改错误");  
    }  

    _declspec(dllexport) void sysnap()  
    {   
    const int nBufSize = MAX_COMPUTERNAME_LENGTH + 1;    

     DWORD nSize = nBufSize;   

     char name[nBufSize];   
        
     GetComputerName(name,&nSize);   
        
     MessageBox(NULL,name,TEXT("信息"), MB_ICONINFORMATION );   

    }   
    在 

    好了,开始编译.得到了一个DLL,它导出了俩个函数名 
    ?sysnap@@YAXXZ?SetTime@@YAXXZ 
    下面我们要用到的名字就是这俩个,,,呵呵,是不是感觉很难记,有没有可以直接导出 

    sysnap这样的名字,有//...在VC编写前可以自己弄,这里我就不说(其实我再弄的时候没考 

    虑到导出名,呵呵..不过已经编译好了.算了) 

    3编写加载我们DLL的Loader,实现一个类似RUNDLL32.EXE的程序 
    好了,我们的DLL已经编写好了,现在就是运行它了,当然不可能双击运行,我们需要编写一 

    个加载这个DLL的Loader 
    依然是打开VC,编写控制台程序,我命名为sysnap..所以编译后得到sysnap.exe 
    代码如下  

    #include <windows.h> 
    #include <stdio.h> 
    void main() 

    typedef int (*ADDPROC)(); 
    HINSTANCE hInst; 

    char funName[30]; 
    char dllName[30]; 
    printf("______献给黑吧______"); 
    printf("想使用哪个DLL中的函数:\n"); 
    scanf("%s",dllName); 
    hInst=LoadLibrary(dllName); 
    if(hInst) 

    printf("%s加载成功",dllName); 

    else 

    return; 

    printf("想使用%s中的哪个函数\n",dllName); 
    scanf("%s",funName); 

    ADDPROC HOOK=(ADDPROC)GetProcAddress(hInst,funName); 
    if(!HOOK) 

    printf("失败!"); 
    return; 

    else 
    { //hwnd=GetConsoleHwnd(); 
    HOOK(); 
     printf("成功!"); 
    int a; 
    scanf("%d",&a); 

    编译它,得到一个EXE程序,把我们的sysnap.dll放到跟它同一个目录下,这样可以方便快速 找个我们的dll,现在可以按照我们这个程序运行我们的DLL了,依次输入sysnap.dll,?  sysnap@@YAXXZ看到没,弹出一个窗口,里面显示了我们的电脑用户名..你也可以运行第二  个函数,sysnap.dll....?SetTime@@YAXXZ...因为开始没考虑到导出名字问题,所以写到这就算了...如果想导出sysnap和SetTime这样的函数名是可以的,怎么弄你自己上网查下本来还想写是弄成rundll32.exe形式的,不过没什么意义就算了,,其实也很简单...就是用main()的俩个参数argv和argc..有兴趣可以自己实现 4线程注入之Loader编写

    大家知道,上面的sysnap.exe是来加载我们的DLL..那就是说如果把进程sysnap.exe关掉, 那DLL也被卸载,那有没有办法让我们的loader运行一次,然后我们的dll就一直运行而无论 sysnap.exe进程是否被关掉,有..那就是线程注入,把我们的dll注入到别的进程...接下来 

    我们就是来实现这样一个loader..测试的dll的代码在前几天我的章里有 
    http://tieba.baidu.com/f?kz=304645377这个DLL是有DLLMain()的..详细参考<<windows 核心编程>>好了... 
    主要思想是根据我们要注入的进程名得到它的ID,然后是提权,最后就是注入 
    代码如下..可以看下<<windows核心编程和MSDN>> 
    #include <windows.h>  
    #include <stdio.h> 
    #include <Tlhelp32.h> 

    BOOL InjectDll(const char *DllFullPath, const DWORD dwRemoteProcessId); 
    int Hightpriv(const char * name) ; 
    DWORD GetProcessIdByName(LPCTSTR name); 

    int main() 
    {  
     char strname[30]; 
     char dllname[30]; 
     int proID; 
     printf("想注入哪个进程,比如explorer.exe,请注意大小写,:"); 
     scanf("%s",strname); 
     printf("想把哪个dll注入,请填好完整路劲名:"); 
     scanf("%s",dllname); 
     proID=GetProcessIdByName(strname); 
      
     InjectDll(dllname,proID) ; 
     return 0;  
    }  


    //开始我们的工作了,<<windows核心编程里讲的比较细>> 
    BOOL InjectDll(const char *DllFullPath, const DWORD dwRemoteProcessId)  
    {  
     HANDLE hRemoteProcess;  
     Hightpriv(SE_DEBUG_NAME);  
     char *pszLibFileRemote; 
      
    hRemoteProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId); 

    pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, lstrlen 

    (DllFullPath)+1, MEM_COMMIT, PAGE_READWRITE);  
      
    WriteProcessMemory(hRemoteProcess,pszLibFileRemote, (void *) DllFullPath,  

    lstrlen(DllFullPath)+1, NULL);  

    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress 

    (GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");  
      
     HANDLE hRemoteThread;  
     if( (hRemoteThread = CreateRemoteThread(
    hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL) ) == NULL)  
     {  
     printf("注入线程失败!");  
     return FALSE;  
     }  

      
     CloseHandle(hRemoteProcess); 
     CloseHandle(hRemoteThread); 
     return TRUE;  
    }  

    //提高我们程序的权限,因为我们要操作的是系统中的其他进程,如果没有足够的系统权限,我们是无法写入甚至连读取其它进程的内存地址的 
    int Hightpriv(const char * name)  
    {  
     HANDLE hToken;  
     TOKEN_PRIVILEGES tp;  
     LUID luid;  
      
     OpenProcessToken(GetCurrentProcess(),  
     TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,  
     &hToken);  
      
     LookupPrivilegeValue(NULL,name,&luid) ; 
      
     tp.PrivilegeCount = 1;  
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
     tp.Privileges[0].Luid = luid;  
      
     AdjustTokenPrivileges(hToken,0,&tp,sizeof 

    (TOKEN_PRIVILEGES),NULL,NULL);  
     return 0;  
    }  

    //主要是枚举进程名,与我们想要注入的做比较,如果是就返回它的ID,ROCESSENTRY32是一 

    个与进程有关的数据结构 
    DWORD GetProcessIdByName(LPCTSTR name) 

     PROCESSENTRY32 prostruct; 
     DWORD id = 0; 
     HANDLE hSnapshot; 
      
     hSnapshot= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 
     prostruct.dwSize = sizeof(PROCESSENTRY32); 
     if(!Process32First(hSnapshot,&prostruct)) 
     return 0; 
     do 
     { 
     prostruct.dwSize = sizeof(PROCESSENTRY32); 
     if(!Process32Next(hSnapshot,&prostruct)) 
     break; 
     if(strcmp(prostruct.szExeFile,name) == 0) 
     { 
     id = prostruct.th32ProcessID; 
     break; 
     } 
     }while(TRUE); 
     CloseHandle(hSnapshot); 
     return id; 

    编译后得到了一个EXE文件,现在我们把我们的DLL注入到notepad.exe..这个dll的代码可以在http://tieba.baidu.com/f?kz=304645377的到,自己编译一下.. 
    好了,线程注入就这么完成


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/carl2380/archive/2009/11/13/4805606.aspx

  • 相关阅读:
    不同数据库中两列字段相减(某列有空值)
    ASP.Net MVC利用NPOI导入导出Excel
    ASP.Net MVC中数据库数据导出Excel,供HTTP下载(转)
    Asp.net操作Excel(终极方法NPOI)(转)
    开发中可能会用到的几个 jQuery 小提示和技巧(转)
    最火的.NET开源项目(转)
    sql行转列和列转行(转)
    run fsck manually
    RTP-实时协议
    linux环境几个特殊的shell变量
  • 原文地址:https://www.cnblogs.com/carl2380/p/2093327.html
Copyright © 2020-2023  润新知