首页
社区
课程
招聘
[求助][求助]如何不调用系统API就能创建一个进程?
发表于: 2014-7-21 11:17 9541

[求助][求助]如何不调用系统API就能创建一个进程?

2014-7-21 11:17
9541
最近再做一个研究,如何不调用系统的API来创建一个进程, 为了是躲过创建进程过程中其它软件对相关的API的hook(监控), 我把kernel32.dll复制了到d盘根目录, 改名为Mykernel32.dll,然后调用如下代码想创建一个进程,可是总是创建不成功, 请教各位大侠一下是什么原因, 有懂的请不吝赐教!!

typedef BOOL (WINAPI *MyCreateProcess)(
         LPCSTR lpApplicationName,
         LPSTR lpCommandLine,
         LPSECURITY_ATTRIBUTES lpProcessAttributes,
         LPSECURITY_ATTRIBUTES lpThreadAttributes,
         BOOL bInheritHandles,
         DWORD dwCreationFlags,
         LPVOID lpEnvironment,
         LPCSTR lpCurrentDirectory,
         LPSTARTUPINFOA lpStartupInfo,
         LPPROCESS_INFORMATION lpProcessInformation
    );

HMODULE hMyKernel32 = LoadLibrary("d:\\Mykernel32.dll");
  if(hMyKernel32 == NULL)
  {
    return;
  }
  
  MyCreateProcess MyCreateProcessFun;
  MyCreateProcessFun = (MyCreateProcess)GetProcAddress(hMyKernel32, "CreateProcessA");

  char szCommandLine[] = "notepad";
  STARTUPINFO si = {sizeof(si)};
  PROCESS_INFORMATION pi;
  si.dwFlags = STARTF_USESHOWWINDOW;//指定wShowWindow成员有效
  si.wShowWindow = SW_SHOW;//此成员设为TRUE的话则显示新建进程的主窗口

  BOOL bRet = MyCreateProcessFun(
    "c:\\windows\\system32\\notepad.exe",
    NULL,
    NULL,//默认进程安全性
    NULL,//默认进程安全性
    FALSE,//指定当前进程内句柄不可以被子进程继承
    0,//为新进程创建一个新的控制台窗口
    NULL,//使用本进程的环境变量
    NULL,//使用本进程的驱动器和目录
    &si,
    &pi);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (22)
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
加载之后还需要做一下重定位,让新模块去访问旧模块的数据,不然内部有些过程调用时需要的数据在新模块中是未初始化过的,肯定会出错
2014-7-21 12:36
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
3
lz不发这贴,我还忘了我有这么个东西呢。
先声明不是我写的,这玩意原来在XP下测试成功。但是创建的程序会丢失XP风格。
刚在win8.1下编译测试了一下,创建失败了。

MyCreateprocess.zip
上传的附件:
2014-7-21 13:16
0
雪    币: 114
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
http://blog.csdn.net/mydo/article/details/8121724
2014-7-21 13:57
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
5
受教了
2014-7-21 13:59
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
achillis能不能再说详细一些呢,Mykernel32.dll加载起来应该就调用ntdll.dll中的东西,有哪些东西需要重定位的?
2014-7-21 14:06
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=bxc;1302477]lz不发这贴,我还忘了我有这么个东西呢。
先声明不是我写的,这玩意原来在XP下测试成功。但是创建的程序会丢失XP风格。
刚在win8.1下编译测试了一下,创建失败了。

MyCreateprocess.zip[/QUOTE]

谢谢你了, 你发的这个程序我也有, 但是不太完善, 参数也不好控制,还有win7以上不能用, 所以不太想用这种直接调用底层api来实现,最好还是能通过我上面的办法来做,不过还是谢谢你的热心.
2014-7-21 14:10
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
8
那期待有更好的解方法,别忘了分享下源码
2014-7-21 14:37
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
一定会的
2014-7-21 16:58
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
我指的是kernel32.dll自己的数据,它访问ntdll的数据是通过接口访问的,没有问题
2014-7-21 21:09
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
00EBA3FB 68 C0 02 00 00       push        2C0h
00EBA400 68 D0 A5 EB 00       push        0EBA5D0h
00EBA405 E8 CC 80 FE FF       call        00EA24D6
00EBA40A A1 CC 56 F2 00       mov         eax,[00F256CC]
00EBA40F 89 45 E4             mov         dword ptr [ebp-1Ch],eax
00EBA412 8B 45 0C             mov         eax,dword ptr [ebp+0Ch]

kernel32.dll本来基址应该是7C800000, 现在我用LoadLibrary("Mykernel32.dll");
基址为00EB0000, 发现Loadlibrary会自己重定位,应该不会我们再手动重定位了吧?
2014-7-22 10:01
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
自己顶一下!!!
2014-7-22 12:04
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
13
是啊,LoadLibrary确实做了重定位了,所以它的内部函数访问数据的时候访问的是00EB0000为基址的这个模块的数据,问题是这里面有一些数据是错误的或者未初始化过的,使用的时候会有问题,所以要自己做重定位让模块00EB0000的代码去访问7C800000的数据,这样就OK了~
程序嘛,无非就是代码和数据,重加载的模块,代码是没有问题的,再让它访问原来的数据,和调用原始CreateProcess时就完全没有差别了,这时候代码一样,数据也一样,执行结果应该也是一样的
2014-7-22 12:17
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
14
另外,你这种办法在XP下可以,win7这样LoadLibrary Mykernel32会失败的,还不如自己去Load呢,只需要CreateFile/ReadFile/VirtualAlloc就可以了,自由度更大,可以做更多手脚,还能避过N多监控,比如某些Notify啥的
2014-7-22 12:46
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
15
刚动手调试了一下,Win7下失败是失败在LdrpCallInitRoutine的时候,So,改成这样调用:
LoadLibraryEx("D:\\Mykernel32.dll",0,DONT_RESOLVE_DLL_REFERENCES);

这样就不会去call DllMain了,但是完全不影响使用,Win7测试成功~
2014-7-22 13:15
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
谢谢achillis的分析,让我的思路清晰了很多, 但是我自己重定位了一下, 还是不行,我测试的环境是xp,用LordPE看kernel32.dll的区段如下:
         voffset          vsize
.text    00001000     000831E9
.data   00085000     00004460
.rsrc     0008A000     00008D3FC
.reloc   00118000     00005C84

我重定位了代码段中访问.data的数据,效果如下:
00E7159F FF 75 0C             push        dword ptr [ebp+0Ch]
00E715A2 8D 45 F8             lea         eax,[ebp-8]
00E715A5 50                   push        eax
00E715A6 FF 15 94 12 E6 00    call        dword ptr ds:[0E61294h]
00E715AC 83 3D E0 56 88 7C 00 cmp         dword ptr ds:[7C8856E0h],0  //这个全局变量已经重定位好了
00E715B3 6A 01                push        1

//下面是重定位的代码, 我只是简单写了一下, 没有写通用的, 只是想看看能不能成功
void ReLocationData(HMODULE hModule)
{
        DWORD dwImageBase = (DWORD)hModule;
        DWORD dwBaseOfCode, dwSizeOfCode;
        DWORD dwBaseOfData, dwSizeOfData;
        DWORD dwOriginalBaseOfData;
        DWORD dwValue;
        DWORD mbi_thunk;
       
        if(hModule == NULL)
                return;

        dwBaseOfCode = dwImageBase + 0x1000;
        dwSizeOfCode = 0x831E9;
        dwBaseOfData = dwImageBase + 0x85000;
        dwSizeOfData = 0x4460;
        dwOriginalBaseOfData = 0x7C885000;   //kernel32.dll的.data的起始地址

        VirtualProtect((BYTE*)dwBaseOfCode, dwSizeOfCode, PAGE_READWRITE, &mbi_thunk);
        for(DWORD i = 0; i < dwSizeOfCode - 4; i ++)
        {
                dwValue = *(DWORD*)(dwBaseOfCode + i);
                if(dwValue > dwBaseOfData && dwValue < (dwBaseOfData + dwSizeOfData))
                {
                        *(DWORD*)(dwBaseOfCode + i) = dwValue - dwBaseOfData + dwOriginalBaseOfData;
                }
        }
        VirtualProtect((BYTE*)dwBaseOfCode, dwSizeOfCode, mbi_thunk, &mbi_thunk);
}

现在数据和代码都对上了, 还是不成功。跟过跟踪发现前面所有的步骤都是正常的, 包括NtCreateProcess, NtCreateThread等, 就是最后一步NtResumThread恢复线程运行后整个进程就结束了,不知道这是为什么,希望achillis再给指点一下!
2014-7-23 11:51
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
17
好吧,我直接扔代码了。。。。  
可能是你做的重定位不完整吧
testCreateProc.rar
上传的附件:
2014-7-23 12:28
0
雪    币: 712
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
[QUOTE=achillis;1303026]好吧,我直接扔代码了。。。。  
可能是你做的重定位不完整吧
testCreateProc.rar[/QUOTE]

果然是大牛, 俺佩服!!!
2014-7-23 21:28
0
雪    币: 74
活跃值: (248)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
自己拷贝kernel32还不如调用ntdll的函数.....不过如果对方hook了Nt函数的话  结果还是一样..........
2014-7-24 22:45
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习下achillis代码
2014-7-25 09:07
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
21
自己加载kernel32和ntdll,然后处理下mykernel32的导入表使它转向到myntdll,一样很简单~
2014-7-25 12:45
0
雪    币: 245
活跃值: (469)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
顶一下 achillis
2014-7-27 07:57
0
雪    币: 474
活跃值: (1182)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
... 楼上的方法不错 自己实现一遍
2014-7-29 16:35
0
游客
登录 | 注册 方可回帖
返回
//