当前位置: 首页 > 编程日记 > 正文

VC下提前注入进程的一些方法2——远线程带参数

在前一节中介绍了通过远线程不带参数的方式提前注入进程,现在介绍种远线程携带参数的方法。(转载请指明出处)

1.2 执行注入的进程需要传信息给被注入进程

因为同样采用的是远线程注入,所以大致的思路是一样的,只是在细节上要注意一些处理。总体来说分为以下几个步骤:

1 将需要传递的信息写入被注入进程的地址空间。

2 将远线程函数体写入被注入进程的空间。

3 在被注入进程中执行该远线程函数,让该线程利用我们之前写入的参数完成任务。

在被注入进程的地址空间中写入“需要传递”的信息不存在什么问题,因为该信息是”死的“”数据“,我们写入什么内容就是什么内容,它就是二进制数据。但是写入函数执行体就存在一定的问题。首先我们要考虑用什么语言来写这个函数?我是VC程序员,当然优先选择C++/C。可是使用这些语言往往会存在问题,因为我们不知道编译器对我们的代码可能做了什么手脚。下面我来验证下

    typedef struct _RemoteThreadRountineParam_{//LPLoadLibrary lpLoadLibraryW;//LPGetProcAddr lpGetProcAddress;WCHAR wszDllPath[MAX_PATH];CHAR szFuncName[MAX_FUNCNAMELENGTH];HANDLE hEvent;}RemoteThreadRountineParam,*pRemoteThreadRountineParam;
DWORD WINAPI RemoteThreadRoutine_Error( LPVOID lpParam ){if ( NULL == lpParam ){return 0;}pRemoteThreadRountineParam lpRmtParam = (pRemoteThreadRountineParam) lpParam;if ( NULL == lpRmtParam->lpLoadLibraryW ){return 0;}if ( NULL == lpRmtParam->lpGetProcAddress ){return 0;}HMODULE hHookDll = LoadLibraryW(lpRmtParam->wszDllPath);if ( NULL == hHookDll ){return 0;}LPExportFun lpExportFunAddr = (LPExportFun)GetProcAddress( hHookDll, lpRmtParam->szFuncName );if ( NULL == lpExportFunAddr ){return 0;}lpExportFunAddr( lpRmtParam->hEvent );return 0;}

回想前一节中,我们将DLL的绝对路径写入被注入进程的空间作为远线程的唯一参数,而本节的远线程需要很多参数,所以我们要定义一个结构体RemoteThreadRountineParam。它包含的成员是:要注入的DLL的绝对路径、这DLL中的导出函数名,以及这个导出函数需要的参数——Event句柄。远线程执行的函数体是RemoteThreadRoutine_Error,其参数是一个指向RemoteThreadRountineParam结构体对象的一个指针,正如其名字——它是Error的。其执行的逻辑也是很简单的:加载DLL,寻找导出函数和执行导出函数。之后我们所有带参数的注入逻辑都将采用这个最基本的处理流程,只是细节处理上存在一定的区别。

do {// 写入线程例程代码// 分配内存空间pBufferRemoteFun = VirtualAllocEx( hProcess, NULL, dwFunMemSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );       if ( NULL == pBufferRemoteFun ) {break;}// 将信息写入傀儡进程的内存地址空间if ( FALSE == WriteProcessMemory( hProcess, pBufferRemoteFun, pRmtRoutine, dwFunMemSize, NULL ) ) {break;}do {pBufferParam = VirtualAllocEx( hProcess, NULL, dwParamMemSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );if ( NULL == pBufferParam ) {break;}if ( FALSE == WriteProcessMemory( hProcess, pBufferParam, &RmtThdRtParam, dwParamMemSize, NULL ) ) {break;}do {// 注入线程pRemoteThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pBufferRemoteFun, pBufferParam, 0, NULL );if ( NULL == pRemoteThread ) {break;}

这段逻辑分别对应于刚介绍的三个步骤。其中dwFunMemSize是我们定义的一个”足够大“的空间大小,因为我这儿没有计算准确的函数执行体大小(其实我也不知道怎么去计算这个大小)。因为我们的函数执行体代码是要执行的,所以我们申请的空间是具有EXECUTE属性的。pBufferRemoteFun是指向远线程函数执行体的在”远程“的空间。pRmtRoutine是指向远线程函数执行体的在”本地“的空间。其他没有什么好介绍的,我们将主要的注意力放在pRmtRoutine。

最简单的方式是

char* pRmtRoutine = (char*)RemoteThreadRoutine_Error;

但是我们debug的结果是 “‘0x000a432c’指令引用的‘0x0000a432c’内存。该内存不能为‘written’”。可以见得我们写入的远线程代码存在问题。现在我们用windbg调试下。在调试前,我们先调整下VC代码为

// 注入线程pRemoteThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pBufferRemoteFun, pBufferParam, 0, NULL );if ( NULL == pRemoteThread ) {break;}ResumeThread( hThread );// 等待远线程激活事件if ( WAIT_OBJECT_0 != WaitForSingleObject( hEvent, 10 * 1000 ) ) {// 等待出错,退出进程//::TerminateProcess( hProcess, 0 );}else {// 等待成功,恢复进程ResumeThread( hThread );}

注意此处,我不会在线程执行失败后立即TerminateProcess,否则我们windbg准备调试被注入进程时,被注入进程可能已经就被杀掉了。而且因为之前我们是以挂起方式创建被注入进程的,所以在执行完创建远线程后,要ResumeThread主线程。否则我们在远线程挂了后,windbg没法挂到任何一个线程上。调试的过程是:

1 用VC在CreateRemoteThread上下断点,F5,断到这个函数执行前。记下pBufferRemoteFun的值。

2 用windbg附加到被注入进程上。

3 在VC中F5,让被注入进程出现错误,以让windbg捕获。

4 在windbg中F5。

会出现以下信息

(d20.8d8): Break instruction exception - code 80000003 (first chance)
eax=002d1eb4 ebx=7ffdb000 ecx=00000003 edx=00000008 esi=002d1f48 edi=002d1eb4
eip=7c92120e esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
_no_process_!DbgBreakPoint:
7c92120e cc              int     3

看不出什么信息。但是我们可以借助pBufferRemoteFun的值(假设为0x000a0000 ),在windbg命令框中输入0x000a0000 0x000a0100。出现如下信息

000a0000 e927430000      jmp     000a432c
000a0005 e902360000      jmp     000a360c
000a000a e9ad6d0000      jmp     000a6dbc
……

这是神马?这是debug环境下增量编译(incremental linking)的一种表现。这儿说说增量编译,增量编译如同在“调用”和“函数执行逻辑”之间插入一个“地址转换层”。比如我们有个函数A,我们调用A的汇编是Call 0x00ABCDEF,那么修改A函数代码后编译,这个0x00ABCDEF地址会发生改变。因为Call指令分为两步,其中第二步是jmp到A函数逻辑的入口点,jmp的偏移是需要计算的。于是我们频繁修改A的函数逻辑,会导致频繁的计算A函数逻辑偏移地址(想想整个PE文件中所有调用都要再算一次jmp偏移是不是很浪费)。于是一种解决方案是,调用A时就Call一个固定地址,该地址指令是jmp到一个固定的地址,这个地址保存的是真实调用A的代码。这样每次编译只用修改“转换层”中的jmp偏移即可。

回到我们的问题,用u 0x000a432c可以发现这个内存空间不存在汇编代码。因为我们写错内容了,我们要写入的远线程函数的逻辑代码。那么我们将jmp过滤掉。

        // JMP过渡if ( (char)0xE9 == *pRmtRoutine ) {DWORD dwOffset = 0;memcpy_s( &dwOffset, sizeof(DWORD), pRmtRoutine + 1, sizeof(DWORD) );// 偏移,1为0xE9,4为dwoffset大小pRmtRoutine = pRmtRoutine + 1 + 4 + dwOffset;}

再试一下我们程序。还是报错,这次错误是“'0x000a0053'指令引用的'0x00424788'内存。该内存不能为'read'”。使用刚才的调试方法,我们发现我们注入的代码如下

000a0000 55              push    ebp
000a0001 8bec            mov     ebp,esp
000a0003 81ece4000000    sub     esp,0E4h
000a0009 53              push    ebx
000a000a 56              push    esi
000a000b 57              push    edi
000a000c 8dbd1cffffff    lea     edi,[ebp-0E4h]
000a0012 b939000000      mov     ecx,39h
000a0017 b8cccccccc      mov     eax,0CCCCCCCCh
000a001c f3ab            rep stos dword ptr es:[edi]
000a001e 837d0800        cmp     dword ptr [ebp+8],0
000a0022 7507            jne     000a002b
000a0024 33c0            xor     eax,eax
000a0026 e983000000      jmp     000a00ae
000a002b 8b4508          mov     eax,dword ptr [ebp+8]
000a002e 8945f8          mov     dword ptr [ebp-8],eax
000a0031 8b45f8          mov     eax,dword ptr [ebp-8]
000a0034 833800          cmp     dword ptr [eax],0
000a0037 7504            jne     000a003d
000a0039 33c0            xor     eax,eax
000a003b eb71            jmp     000a00ae
000a003d 8b45f8          mov     eax,dword ptr [ebp-8]
000a0040 83780400        cmp     dword ptr [eax+4],0
000a0044 7504            jne     000a004a
000a0046 33c0            xor     eax,eax
000a0048 eb64            jmp     000a00ae
000a004a 8b45f8          mov     eax,dword ptr [ebp-8]
000a004d 83c008          add     eax,8
000a0050 8bf4            mov     esi,esp
000a0052 50              push    eax
000a0053 ff1588474200    call    dword ptr ds:[424788h]
000a0059 3bf4            cmp     esi,esp
000a005b e8c0bbffff      call    0009bc20
000a0060 8945ec          mov     dword ptr [ebp-14h],eax
000a0063 837dec00        cmp     dword ptr [ebp-14h],0
000a0067 7504            jne     000a006d
000a0069 33c0            xor     eax,eax
000a006b eb41            jmp     000a00ae
000a006d 8b45f8          mov     eax,dword ptr [ebp-8]
000a0070 0510020000      add     eax,210h
000a0075 8bf4            mov     esi,esp
000a0077 50              push    eax
000a0078 8b4dec          mov     ecx,dword ptr [ebp-14h]
000a007b 51              push    ecx
000a007c ff1504474200    call    dword ptr ds:[424704h]
000a0082 3bf4            cmp     esi,esp
000a0084 e897bbffff      call    0009bc20
000a0089 8945e0          mov     dword ptr [ebp-20h],eax
000a008c 837de000        cmp     dword ptr [ebp-20h],0
000a0090 7504            jne     000a0096
000a0092 33c0            xor     eax,eax
000a0094 eb18            jmp     000a00ae
000a0096 8bf4            mov     esi,esp
000a0098 8b45f8          mov     eax,dword ptr [ebp-8]
000a009b 8b8850020000    mov     ecx,dword ptr [eax+250h]
000a00a1 51              push    ecx
000a00a2 ff55e0          call    dword ptr [ebp-20h]
000a00a5 3bf4            cmp     esi,esp
000a00a7 e874bbffff      call    0009bc20
000a00ac 33c0            xor     eax,eax
000a00ae 5f              pop     edi
000a00af 5e              pop     esi
000a00b0 5b              pop     ebx
000a00b1 81c4e4000000    add     esp,0E4h
000a00b7 3bec            cmp     ebp,esp
000a00b9 e862bbffff      call    0009bc20
000a00be 8be5            mov     esp,ebp
000a00c0 5d              pop     ebp
000a00c1 c20400          ret     4

我们查看之前报错的0x000a0053行call    dword ptr ds:[424704h],这个函数地址不是被注入进程空间的函数地址,像之后000a007c ff1504474200    call    dword ptr ds:[424704h]也是会报错的。那么这两个函数是啥?我在VC中Alt+8查看远线程函数的汇编代码,可以发现call    dword ptr ds:[424704h]对应于LoadLibraryW这个函数。0x00424704h保存的是0x7c80aeeb。我们用windbg加载并运行注入进程的PE文件,break后查看相关地址命令

0:002> u 0x7c80aeeb
kernel32!LoadLibraryW:
7c80aeeb 8bff            mov     edi,edi
7c80aeed 55              push    ebp
7c80aeee 8bec            mov     ebp,esp
7c80aef0 6a00            push    0
7c80aef2 6a00            push    0
7c80aef4 ff7508          push    dword ptr [ebp+8]
7c80aef7 e8f96bffff      call    kernel32!LoadLibraryExW (7c801af5)
7c80aefc 5d              pop     ebp
0:002> u 0x7c801af5
kernel32!LoadLibraryExW:
7c801af5 e9f2e7cf84      jmp     015002ec
7c801afa 807ce8d509      cmp     byte ptr [eax+ebp*8-2Bh],9
7c801aff 0000            add     byte ptr [eax],al
7c801b01 33ff            xor     edi,edi
7c801b03 897dd8          mov     dword ptr [ebp-28h],edi
7c801b06 897dd4          mov     dword ptr [ebp-2Ch],edi
7c801b09 897de0          mov     dword ptr [ebp-20h],edi
7c801b0c 897de4          mov     dword ptr [ebp-1Ch],edi

可以想到,0x7c80aeeb是Kernel32.dll文件在该进程中LoadLibrary的函数入口地址。所以我们call    dword ptr ds:[424704h]时,被注入进程中424704h保存的是啥是不确定的。但是,如我在前一节介绍的,windows程序加载kernel32.dll的基地址一般是一样的,于是我们要是将0x7c80aeeb这个值直接传给远线程,应该就可以了。同样的问题存在于我们之前对GetProcAddress的调用,于是我们将这些函数地址以参数形式传入被注入进程。

RemoteThreadRountineParam RmtThdRtParam;RmtThdRtParam.lpGetProcAddress = GetProcAddress;RmtThdRtParam.lpLoadLibraryW = LoadLibraryW;wmemset( RmtThdRtParam.wszDllPath, 0, MAX_PATH );wcscpy_s( RmtThdRtParam.wszDllPath, MAX_PATH, lpDllPath );std::string strFuncName = "ExportFun";memset( RmtThdRtParam.szFuncName, 0 , MAX_FUNCNAMELENGTH );memcpy_s( RmtThdRtParam.szFuncName, MAX_FUNCNAMELENGTH, strFuncName.c_str(), strFuncName.length() );

远线程的代码改为

        HMODULE hHookDll = (lpRmtParam->lpLoadLibraryW)(lpRmtParam->wszDllPath);if ( NULL == hHookDll ){return 0;}LPExportFun lpExportFunAddr = (LPExportFun)(lpRmtParam->lpGetProcAddress)( hHookDll, lpRmtParam->szFuncName );if ( NULL == lpExportFunAddr ){return 0;}lpExportFunAddr( lpRmtParam->hEvent );

F5。还是报错。这次的错误是“'0x0009bc20'指令引用的'0x0009bc20'内存。该内存不能为'written'”。继续使用之前的调试方法,发现我们注入的代码中有如下一行

000a0053 8b4df8          mov     ecx,dword ptr [ebp-8]
000a0056 8b11            mov     edx,dword ptr [ecx]
000a0058 ffd2            call    edx
000a005a 3bf4            cmp     esi,esp
000a005c e8bfbbffff      call    0009bc20
000a0061 8945ec          mov     dword ptr [ebp-14h],eax
000a0064 837dec00        cmp     dword ptr [ebp-14h],0
000a0068 7504            jne     000a006e

我们再在VS中查看我们的远线程反汇编代码有如下

00415A2C E8 BF BB FF FF   call        @ILT+1515(__RTC_CheckEsp) (4115F0h) 

E8BFBBFFFF这条指令是引起被注入进程崩溃的原因,这指令是RTC检查函数,默认情况下VC会给我们的代码做些手脚,这个就是个例子。我们对远线程代码关闭RTC检查。

#pragma runtime_checks( "scu", off )DWORD WINAPI RemoteThreadRoutine_Error( LPVOID lpParam ){……}
#pragma runtime_checks( "scu", restore )

运行之,OK了。
        这个过程很忐忑,但是如果不想研究这个,可以选择内嵌汇编方式。因为RTC检查不会在Release版本中做,所以我们可以将远线程函数本地执行一次,在函数的入口处int 3一下,然后用windbg或ollydbg启动之,断在函数入口点,然后我们把其汇编东东扒拉下来就行了。当然会写汇编的同学就直接动手写汇编代码就行了。

__declspec(naked) DWORD WINAPI RemoteThreadRoutineASM( LPVOID lpParam ){__asm{push esi// 检测指针参数mov     esi, [esp+8]pushadpushfdtest    esi, esijz      short End// 检测参数第一个成员mov     eax, [esi+4]test    eax, eaxjz      short End// 检测参数第二个成员mov     eax, [esi]test    eax, eaxjz      short Endlea     ecx, [esi+8]push    ecxcall    eaxtest    eax,eaxjz      short Endlea     edx, [esi+210h]push    edxpush    eaxmov     eax, [esi+4]call    eaxtest    eax,eaxjz      short Endmov     ecx, [esi+250h]push    ecxcall    eaxEnd:xor     eax, eaxpopfdpopadpop     esiretn    8}}

一定要加__declspec(naked),否则起不来哦!
        (转载请指明出处)

相关文章:

芬兰开放“线上AI速成班”课程,全球网民均可免费观看

出品 | AI科技大本营(ID:rgznai100)去年,芬兰推出了一个免费的“人工智能线上速成班”项目,目的是向该国民众教授与新技术有关的知识。现在,作为送给全世界的圣诞节礼物,这个项目已面向全球网民开放访问&am…

deepin开通ssh

1、在终端打入下面命令进行安装sudo apt-get install openssh-server2、启用sshservice ssh start 反馈:start: Rejected send message, 1 matched rules; type"method_call", sender":1.56" (uid1000 pid2272 comm"start ssh ") int…

实现等待窗体的几种方式

实现等待窗体的几种方式:下面说明了五种可以实现等待窗体的方式,其中三种给出了代码。准备资料安全访问控件成员为了保证在创建控件的线程上调用控件成员,用下面的方式封装控件的属性、方法、其他自定义成员的访问。如: winWordControl.LoadD…

GitHub宝藏项目标星1.6w+,编程新手有福了

作者 | Rocky0429来源 | Python空间(ID: Devtogether)特别惭愧的是,虽然我很早就知道 GitHub,但是学会逛 GitHub 的时间特别晚。当时一方面是因为菜,看着这种全是英文的东西难受,不知道该怎么去玩&#xff…

VC下提前注入进程的一些方法3——修改程序入口点

前两节中介绍了通过远线程进行注入的方法。现在换一种方法——修改进程入口点。(转载请指明出处) 在PE文件中,其中有个字段标识程序入口点位置。我们通过这个字段,到达程序入口点。PE文件的结构我这儿不讨论(我会在之后…

如何产生签名applet能让applet能够访问本地资源

2019独角兽企业重金招聘Python工程师标准>>> 如何产生签名applet,以使applet能够访问本地资源? 在jdk1.1中,可以使用javakey命令来产生公钥,私钥,证书和签名的jar文件,详细资料请参考: http://java.sun.com/security/usingJavakey.html而java 2对签名机制做了比较大…

VC提前注入.net软件的方法

在之前几节介绍了各种注入方法,但是这些方法存在一些缺陷——对.net程序注入无效。(转载请指明出处) 这个可以理解,.net程序的代码不是汇编,而是微软自定义的IL中间语言。.net CLR如同虚拟机,解析并执行这些…

活动推荐:语音和语言技术在自然交互中的实践沙龙

智能语音技术已经渗透进家居生活、车载、金融服务等日常生活场景,在很大程度上解放了人们的双手和眼睛,语音交互成为连接人与信息/服务的新入口。根据IDC预测,国内对话式人工智能市场规模将在2022年达到78亿元。如何提供便捷、高效、高可用的…

JS字符串 window.open() window.opener window.name window对象总结

晚上总结了一下,发上来分享:字符串 window.open() window.opener window.name window对象等的一点总结 http://download1.csdn.net/down3/20070614/14012050509.rar

dedecms /member/reg_new.php SQL Injection Vul

catalog 1. 漏洞描述 2. 漏洞触发条件 3. 漏洞影响范围 4. 漏洞代码分析 5. 防御方法 6. 攻防思考 1. 漏洞描述 Dedecms会员中心注入漏洞 2. 漏洞触发条件 http://127.0.0.1/dedecms5.5/member/reg_new.php?dopostregbase&step1&mtype%B8%F6%C8%CB&mt…

VC下通过进程ID获取进程镜像文件路径的方法及其存在的缺陷

工作中经常会遇到通过进程ID获取进程镜像文件或者其他模块的路径的需求。(转载请指明出处)网上关于方案大致存在两种方案: OpenProcess->GetModuleFileNameOpenProcess->EnumProcessModules->GetModuleFileNameEx我试验了下&#x…

腾讯云100亿元目标达成,发阳光普照奖iPhone 11 Pro,你酸了吗?

12 月 19 日,鹅厂腾讯发钱的消息又像往年一样引来了一群柠檬精。除了微信支付团队获得 2 亿元奖金的消息之外,一张腾讯云团队每个员工奖励一部 iPhone 11 Pro 的 H5 页面截图也不断地轰炸着朋友圈。原来这张图说的是腾讯云在 Q3 已完成 2019 年全年 100 …

分享一个python cookbook的在线教程地址

分享一个python cookbook的在线教程地址:http://python3-cookbook.readthedocs.org/zh_CN/latest/翻译者:熊能转载于:https://blog.51cto.com/verdureorange/1653514

优化系统后VS启动不了问题的一种解决方案

本文只讨论使用第三方软件优化系统后,或者您主动禁止服务后导致VS不能启动的问题。(转载请指明出处) 记得大概是08年时,我使用一些软件对电脑启动项做了优化。后来打开VS2005时,发现VS2005会一直保持在“载入界面”,当时十分懊恼&…

懂数学的程序员能有多吃香?这是我听过最好的答案丨颠覆认知

懂数学的程序员能有多吃香?关于这个问题,我想每个程序员心中都有自己的答案。之前在网上看到一个很有意思的答案说:我是在做了2年的开发之后,才真正认识到数学对于程序员的重要性,开始系统的学习数学。理由无它&#x…

基于OpenCasCade的程序发布问题

基于OpenCasCade二次开发了一个程序,想采用简单的copy的发布(部署)方式。 但在发布时遇到了很多问题。总结一下。 首先将所有所需的dll拷贝到了执行目录下,然后将程序copy到一台未安装OpenCasCade的机器上运行出错,信…

Unity3D移植到自己的Android程序

用Unity3D开发需要把动画效果移植到现有的APP上面。Unity for Android 比较特殊,Unity for IOS 打包是将XCODE工程直接交给开发者,开发者可以在工程的基础上继续添加新的视图,最后由开发者自行打包生成IPA包,发布程序。而Unity fo…

一种注册表沙箱的思路、实现

从今年4月份开始,我接触到一个沙箱项目。该项目的需求要求我们的沙箱具有良好的安全性和兼容性。当时我们研究了SandBoxIE和360的沙箱,基本确定通过“重定向”思路来实现这款沙箱。而我主要负责研究注册表这块。(转载请指明出处)在…

PyTorch实现L2和L1正则化的方法 | CSDN博文精选

作者 | pan_jinquan来源 | CSDN博文精选目录1.torch.optim优化器实现L2正则化2.如何判断正则化作用了模型?2.1未加入正则化loss和Accuracy2.1加入正则化loss和Accuracy2.3正则化说明3.自定义正则化的方法3.1自定义正则化Regularization类3.2Regularization使用方法4…

构建插件式的应用程序框架(六)----通讯机制(ZT)

前天发了构建插件式的应用程序框架(五)----管理插件这篇文章,有几个朋友在回复中希望了解插件之间是如何通讯的。这个系列的文章写到这里,也该谈谈这个问题了,毕竟已经有了插件管理。不知道大家…

【翻译】将Ext JS Grid转换为Excel表格

原文:Converting an Ext 5 Grid to Excel Spreadsheet稍微迟来的礼物——Ext JS Grid转为Excel代码,现在支持Ext JS 5!功能包括: - 支持分组 - 数字的处理 VS 字符串数据类型 - 对于不支持客户端下载的浏览器会提交回服务器Enjoy&…

AI研究过于集中狭隘,我们是不是该反思了?

作者 | Sergii Shelpuk译者 | 陆离编辑 | 夕颜出品 | AI科技大本营(ID: rgznai100)【导读】2019年是AI领域更加冷静的一年,少了些喧嚣和泡沫,大浪淘沙留下的是经过检验的真正的AI研究者、实践者。但是你也许没有发现,本…

上周回顾:微软与苹果比赛谁更“不安全”

每个月的第二周应该是微软例行发布补丁的日子,本周也不例外,微软如定期新闻发布会一样公布了自己的安全公告。这本来已经成了例如51CTO.com这样关注企业网络安全的媒体重要的素材,不过没想到的是本周苹果偏要抢这个风头……热点一&#xff1a…

一种注册表沙箱的思路、实现——注册表的一些基础知识

要做注册表沙箱,就必须要了解部分注册表知识。而注册表的知识很多,本文主要讲述如何在win32系统是上识别注册表映射的。(转载请指明出处) 在我的xp 32bit系统上,WinR regedit之后打开注册表管理器。我们可以看到如下主…

bzoj 2565: 最长双回文串 manacher算法

2565: 最长双回文串 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id2565 Description 顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆…

44岁的微软如何刷新未来?

整理 | 伍杏玲出品 | AI科技大本营(ID:rgznai100)在当今的“云”时代,很多企业在多个云计算平台部署应用,且需要统一管理和保护应用。在微软Ignite 2019 大会上,为了让企业轻松地在任何类型的基础设施平台上…

一种注册表沙箱的思路、实现——Hook Nt函数

Nt函数是在Ring3层最底层的函数了,选择此类函数进行Hook,是为了提高绕过门槛。我的Hook方案使用的是微软的Detours。(转载请指明出处)Detours的Hook和反Hook的写入如下: DetourTransactionBegin(); DetourUpdateThread…

浅析Struts 体系结构与工作原理(图)

Struts 体系结构是目前基于java的 web系统设计中广泛使用的mvc构架。基本概念    Struts是Apache 基金会Jakarta 项目组的一个Open Source 项目,它采用模型-视图-控制器(Model-View- Controller,简称MVC)模式,能够…

2015第22周一Web性能测试工具及IE扩展区别

在高性能web测试工具推荐http://www.jb51.net/article/23034.htm中发现了dynaTrace 感觉很不错,不但可以检测资源加载瀑布图,而且还能监控页面呈现时间,CPU花销,JS分析和执行时间,CSS解析时间的等。http://www.ibm.com…