text:
Posted by Mateusz Jurczyk of Google Project Zero
Last month, I presented parts of my PostScript font security research at the REcon security conference in Montreal, in a talk titled "One font vulnerability to rule them all: A story of cross-software ownage, shared codebases and advanced exploitation". This talk discussed the exploitation process of a vulnerability found in the implementation of a BLEND Charstring instruction, discovered in a user-mode Adobe Reader's CoolType library and a kernel-mode Adobe Type Manager Font Driver (ATMFD.DLL) used by Windows, both of which are responsible for supporting Type 1 and OpenType fonts in the Reader and system GDI environments. This research was performed as part of my Project Zero work, and more generally resulted in a multitude of vulnerabilities discovered in different modern font engines, which all share a common ancestor of the Charstring interpreter routine – ranging from low to critical severity flaws. The full breakdown of the identified security issues can be found below, with links pointing to corresponding google-security-research bug tracker entries, containing reports with detailed analysis of the vulnerabilities together with Proof of Concept files, as they were provided to the vendors:
Microsoft Windows (ATMFD)
Adobe Reader (CoolType)
Windows Presentation Foundation
| |
Unlimited Charstring execution
| |
Out-of-bounds reads from the Charstring stream
| ||
Off-by-x out-of-bounds reads/writes relative to the operand stack
| |
Memory disclosure via uninitialized transient array
| ||||
Read/write-what-where in LOAD and STORE operators
| |
Buffer overflow in Counter Control Hints
| ||
Buffer underflow due to integer overflow in STOREWV
| ||
Unlimited out-of-bounds stack manipulation via BLEND operator
As shown above, most of the vulnerabilities were present in more than one font engine, running in different security contexts or privilege levels. All of them were reported to the respective vendors shortly after their discovery, and were subsequently patched by Microsoft in two security bulletins: MS15-021 (March) and MS15-044 (May), while Adobe issued a single APSB15-10 bulletin in May to address all issues affecting Reader.
Some background story on the research can be found in the "Results of my recent PostScript Charstring security research unveiled" blog post, and the slide deck used during my REcon presentation is linked below:
One font vulnerability to rule them all: A story of cross-software ownage, shared codebases and advanced exploitation (PDF, 7.78MB)
To make a long story short, the one vulnerability mentioned in the title is CVE-2015-0093 (also dubbed CVE-2015-3052 by Adobe). What makes it unique is the fact that it provides an extremely powerful primitive, making it possible to perform arbitrary PostScript operations (e.g. arithmetic, logic, conditional and other) anywhere on the exploited thread's stack, with full control over what is overwritten and how. This, in turn, could be used by an attacker to craft a self-contained malicious Type 1 font which, once loaded in the vulnerable environment, reliably and deterministically builds a ROP chain in the Charstring program, consequently defeating all modern exploit mitigations techniques such as stack cookies, DEP, ASLR, SMEP and so on. It also affected both Adobe Reader and the Windows kernel (32-bit), enabling the creation of a single PDF file, which would first achieve arbitrary code execution within the PDF viewer's process, and further escape the sandbox by exploiting the very same bug in the operating system, elevating chosen process' privileges in the system and removing the associated job's restrictions.
In order to demonstrate that the above scenario was in fact possible, I created a Proof of Concept file which does exactly that, targeting the latest versions of the software affected by the bugs: Adobe Reader 11.0.10 and Windows 8.1 Update 1 (32-bit). Considering that 64-bit builds of Windows were not affected by the BLEND vulnerability, I also devised an x64 way to achieve reliable elevation of privileges using another Charstring vulnerability (CVE-2015-0090) found during the research, which also adheres to the "100% reliability" and "all mitigations bypassed" philosophy.
In the upcoming series of blog posts, I will discuss the exploitation of the BLEND vulnerability in more detail, and further extend some of the thoughts mentioned in the slides, sharing my insights and providing more context to those who didn't get a chance to attend the REcon talk in person. Today's part will cover a brief introduction to digital typography and the role PostScript fonts play in it, a Type 1 / OpenType primer, a short guide to reverse engineering the program interpreter found in ATMFD.DLL, and finally a description of the security flaw in the "blend" operator itself. Further posts released in the upcoming weeks will subsequently provide details on the process of exploiting Adobe Reader for remote code execution, and Windows 8.1 32/64-bit for sandbox escapes on both builds of the operating system. Let's start with the beginning!
Some (pre)history
The history of digital typography is almost as old as the history of computing itself. Early personal computers seen in the very early 80's offered a minimalistic user interface, which only allowed input and output to be passed around as text – text that had to be displayed on the screen somehow. Since both hardware and software were very simple and had limited capabilities, text formatting on the display were not an utmost priority back then (more so in the printing industry) with mostly predefined, fixed-width bitmap fonts used at first. Figure 1 shows the different typefaces (implemented in the form of bitmap fonts) designed by Susan Kare and released with the original Mac OS operating system in 1984.
Figure 1. Original typefaces shipped with Mac OS in 1984 (source: https://en.wikipedia.org/wiki/Susan_Kare)
A number of bitmap font formats were designed in the 80's, with some of them still supported by software nowadays, such as Portable Compiled Format (PCF, supported by FreeType), Glyph Bitmap Distribution Format (BDF, supported by FreeType) or Microsoft Windows Bitmapped Font (FON, supported by FreeType and Windows GDI).
Also in 1984, Adobe introduced two outline font formats based on the PostScript language, itself created two years before: Type 1 fonts, which could use a specific subset of the PostScript specification, and Type 3 fonts, which could make use of all of the language's features. This was a huge leap forward, as these fonts would specify the glyph shapes instead of their bitmap representation at a specific point size, making them more extensible, adjustable and universal. These formats were originally proprietary and licensed to Adobe partners; they were only publicly documented in 1990, following Apple's work on an independent format, TrueType. As security researchers looking into PostScript fonts, we should be interested primarily in the Type 1 format (not Type 3), which is the one supported by popular software on desktop computers. The two most important documents are:
A year later in 1991, Adobe released an extension to the Type 1 font format, called Multiple Master fonts, which enabled specifying two or more masters (font styles: weight, width, optical size, style) and interpolating between them along a continuous range of "axes", as shown in Figure 2. From a technical perspective, the extension was implemented by introducing several new Dictionary fields in the Type 1 header, together with several new Charstring instructions. The details of the technology can be found in the "Type 1 Font Format Supplement" linked above. The interesting bit about it is that while it is officially part of the specification and is therefore supported by many modern font engines, it was never commonly adopted worldwide, with just a handful of Multiple Master fonts ever coming to existence, mostly created by Adobe itself. This is something to keep in mind as old, sparse, unknown features of common file formats are often great vulnerability hunting targets. More information about the development of Multiple Master typefaces in Adobe can be found in the "The Adobe Originals Silver Anniversary Story: How the Originals endured in an ever-changing industry" article [1], but we actually recommend the entire "Celebrating 25 Years of Adobe Originals" series [2] for anyone curious about the history of digital typography and Adobe's role in it.
Figure 2. Examples of design axes and dynamic ranges in multiple master typefaces (source: http://blog.typekit.com/2014/07/30/the-adobe-originals-silver-anniversary-story-how-the-originals-endured-in-an-ever-changing-industry/)
In the same year of 1991, Apple designed a completely new outline font format called TrueType as a competitor to Type 1. It was based on the SFNT general file structure (a short header and a number of data sections described by four-byte tag, offset, length and checksum), represented glyph outlines using quadratic bézier curves, and defined a dedicated turing-complete hinting programming language. The format was first supported in Mac OS System 7 released in May 1991, but Apple also licensed it to Microsoft for free in order to ensure wide adoption. As a result, TTF support was introduced in Windows 3.1 released in 1992. It is largely the same code that rasterizes TTF fonts in the most recent versions of Windows today.
Three years later, Apple extended TrueType with the launch of TrueType GX, which introduced new, advanced features such as morphing (similar to Adobe's Multiple Masters) or Line Layout Manager. Microsoft failed to license the format from Apple [3] and started working on a new one, originally called TrueType Open. Adobe would later join Microsoft in these efforts in order to create technology which would supersede both TrueType and Type 1, eventually named OpenType. While OpenType shares the same overall SFNT structure as TrueType, it uses a different set of tables. Furthermore, it can specify glyph outlines in either the old TrueType format ("glyf" table) or a new one called "Compact Font Format" (CFF), which is essentially an extended and binary-encoded equivalent of Type 1. As the most common flavor nowadays, the term "OpenType font" is often used for short of OpenType/CFF.
Basic support for OpenType was implemented in Adobe Type Manager in the early years of the format's development, but in order to have the fonts working in the Windows environment, the program had to be installed separately in Windows 3.0, 3.1, 95, 98, Me and NT. Microsoft then added official support for external font drivers in the operating system, and worked with Adobe to include an Adobe Type Manager Font Driver (ATMFD.DLL) module in default installations starting with Windows 2000. The driver has remained in all further editions of the OS, up to and including Windows 8.1. In the meanwhile, Adobe used the same code to handle OpenType fonts in some of their other products, such as Adobe Reader (the CoolType library), and other projects and vendors followed by also implementing support for the format, too. Overall, OpenType was widely recognized and is now one of two most commonly used font formats together with TrueType.
More recent times
Since late 90's, no groundbreaking revolution has taken place in the form of new font formats. Instead, the existing standards for TrueType and OpenType have been evolving, going through a number of official specification revisions and unofficial extensions implemented by various vendors, often with little to no collaboration with other major actors. For example, Apple introduced SFNT tables enabling more advanced font features supported by AAT (Apple Advanced Typography), Microsoft introduced new math tables supported by Office, Windows 8 (RichEdit 8.0) and Gecko, Mozilla and Adobe proposed adding full SVG support to OpenType and so forth. As a result, security researchers nowadays would be mostly interested in four font formats: FON bitmap fonts as still supported by Microsoft Windows and FreeType, Type 1 PostScript fonts supported by Microsoft Windows, Adobe Reader, FreeType and Oracle Java, as well as TrueType and OpenType fonts (with their various vendor-specific extensions) supported by pretty much every modern font engine. The three most exposed pieces of software would be the FreeType open-source library used by a majority of UNIX-based software (GNU/Linux, iOS, Android, Chrome OS etc.), and Windows GDI / DirectWrite, which are used by most desktop applications running on Windows for font rasterization (e.g. Internet Explorer, Google Chrome, Mozilla Firefox, Microsoft Office etc.).
As it turns out, the above historical background is quite important in the context of today's software security. Considering the extensive collaboration between vendors decades ago, a great number of modern widely used programs and systems share a common ancestor of their font rasterization code. For example, most TTF engines are based on Microsoft's original implementation of the format, including Windows GDI (win32k.sys), Microsoft GDI+, Microsoft DirectWrite, Adobe Reader and Adobe Flash. Likewise, most OTF engines are based on Adobe's original implementation, including Microsoft GDI (ATMFD.DLL), Microsoft DirectWrite, Microsoft Presentation Foundation and Adobe Reader. As a direct outcome, any bugs present in the original implementation that was later branched and included in multiple products were likely propagated, and may affect various programs or operating systems. This is of course an extremely frightful scenario, with a single 0-day vulnerability potentially being used in targeted or mass campaigns against users of different software, or chained to accomplish both remote code execution and a sandbox escape, leading to complete system compromise. Consequently, I believe that due to the high sensitivity of the code area, it deserves special attention from the security community.
Figure 3. Potential security impact of vulnerabilities present in the shared PostScript font implementation.
It is important to note that while the same pieces of code can be found in a variety of modern programs and environments, they have been living in different branches and maintained by different groups of people for many years now. They have very likely received a varied degree of auditing and fuzzing (being more or less valuable targets), which means that they don't have to be affected by the exact same set of bugs today. On one hand, this can be considered good news, since a bug in one of the products won't necessarily affect all the other ones, limiting the impact. On the other hand, security relevant differences in the codebases can reveal issues in the unpatched software through missing sanity checks and similar patterns easy to recognize by reverse engineers using binary diffing tools.
What makes font engines even more sensitive and susceptible to attacks is the fact that the attackers can choose from any of the existing file formats, most of which are extremely complex both structurally and semantically, making it very difficult to get them 100% right in implementation. If we also consider that a majority of the parsers were in a large part developed in C/C++ several decades ago, that they are easily reachable via numerous channels (websites, documents, USB sticks etc.), and that they support extensive, turing-complete virtual machine environments for running untrusted TTF/PostScript Charstring programs, it becomes clear that fonts are one of the best imaginable attack vectors. This is true even despite the great number of vulnerabilities that have already been fixed in virtually every font engine in existence, conference talks given in the past (nearly every major one having a font-related presentation in agenda), and font vulnerabilities being used both "in the wild" (e.g. the Duqu TTF exploit [4], or comex' iOS jailbreak via a FreeType Type 1 vulnerability [5]) and in various hacking competitions such as pwn2own 2013 (Joshua Drake's Java 7 SE OpenType memory corruption vulnerability [6]), or pwn2own 2015 (K33n Team's TTF vulnerability [7]).
Before we dive into discussing the Charstring related vulnerabilities discovered in Type 1 / OpenType handling implemented in ATMFD.DLL and related font engines, let's briefly go through the format and structure of the two PostScript formats.
Type 1 font primer
In essence, Type 1 fonts are a set of so-called "dictionaries" (associative name → value arrays with field-specific primitive types or other nested dictionaries) responsible for specifying the general font properties, and PostScript programs called "Charstrings" describing the shapes of all glyphs supported by the font. An overview of the general font structure is shown in Figure 4.
Figure 4. Typical dictionary structure of a Type 1 font (source: Adobe Type 1 Font Format, Adobe Systems Inc.)
There are a number of file formats related to Type 1 fonts:
- .AFM (Adobe Font Metrics), .ACFM (Adobe Composite Font Metrics), .AMFM (Adobe Multiple Font Metrics) – textual metrics files.
- .PFA (Printer Font ASCII) – textual representation of the core font file.
- .PFB (Printer Font Binary) – binary representation of the core font file.
- .PFM (Printer Font Metric) – binary representation of the font metrics.
- .MMM (Multiple Master Metric) – binary representation of Multiple Master font metrics.
Depending on the environment, various subsets of the above files are necessary to use the font, with .PFB (the main, partially binary encoded font file) and .PFM (binary encoded font metrics) being the most common ones. For example, the AddFontResource Windows API function requires paths to the .PFB and .PFM files separated by a pipe character, with the potential addition of an .MMM file if the font supports multiple masters.
Examining and modifying .PFB files (and especially the Charstrings contained within) is inconvenient due to two major reasons: binary encoding and encryption. As it turns out, Adobe introduced a simple encryption scheme in Type 1 fonts in order to prevent casual inspection by third parties. The full details of the algorithm used to "protect" (or obfuscate, rather) the Private dictionary and Charstrings were only documented when the Type 1 format specification came to light in the 90's. The encryption routine is shown below, with decryption achieved using the same function with minor changes:
unsigned short int r;
unsigned short int c1 = 52845;
unsigned short int c2 = 22719;
unsigned char Encrypt(plain) unsigned char plain;
{unsigned char cipher;
cipher = (plain ^ (r>>8));
r = (cipher + r) * c1 + c2;
return cipher;
(source: Adobe Type 1 Font Format, Adobe Systems Inc.)
In order to work around the encryption and Charstring encoding, we can conveniently use the type1 and detype1 utilities as part of the Adobe Font Development Kit for OpenType (AFDKO) (open source code available on GitHub), which can convert between .PFB and .PFA (textual, human readable) font files:
$ detype1 font.pfb > font.pfa
$ type1 font.pfa > font.pfb
$ detype1 font.pfb > font.pfa
$ type1 font.pfa > font.pfb
At this point, we can freely work with Type 1 fonts, analyzing and modifying them as needed. If we take a quick look into any .PFA file, we will see a number of PostScript programs of the following form:
/at ## -| { 36 800 hsbw -15 100 hstem 154 108 hstem 466 108 hstem 666 100 hstem 445 85 vstem 155 120 vstem 641 88 vstem 0 100 vstem 275 353 rmoveto 54 41 59 57 vhcurveto 49 0 30 -39 -7 -57 rrcurveto -6 -49 -26 -59 -62 0 rrcurveto -49 -27 43 48 hvcurveto closepath 312 212 rmoveto -95 hlineto -10 -52 rlineto -30 42 -42 19 -51 0 rrcurveto -124 -80 -116 -121 hvcurveto -101 80 -82 88 vhcurveto 60 0 42 28 26 29 rrcurveto 33 4 callsubr 8 -31 26 -25 28 -1 rrcurveto 48 -2 58 26 48 63 rrcurveto 40 52 22 75 0 82 rrcurveto 0 94 -44 77 -68 59 rrcurveto -66 59 -81 27 -88 0 rrcurveto -213 -169 -168 -223 hvcurveto -225 173 -165 215 vhcurveto 107 0 92 31 70 36 rrcurveto -82 65 rlineto -32 -20 -64 -12 -83 0 rrcurveto -171 -125 108 182 hvcurveto 172 111 119 168 vhcurveto 153 0 118 -84 -9 -166 rrcurveto -5 -86 -51 -81 -36 -4 rrcurveto -29 -3 12 43 5 24 rrcurveto closepath endchar } |-
As clearly visible, the instruction stream consists of various outline-related instructions interlaced with immediate numbers (operands). To better understand how the program execution works, let's discuss the various components of the execution environment:
- Instruction stream - the stream of encoded instructions used to fetch operators and execute them. Not accessible by the Type 1 program itself.
- Operand stack - a LIFO structure holding up to 24 numeric (32-bit) entries. Similarly to regular PostScript, it is used to store instruction operands. It's important to note that while the maximum width of each entry is 32 bits, different instructions may interpret them in a variety of ways, e.g. as 16.16 fixed points, 16-bit values (discarding part of the information) etc.
- Transient array or BuildCharArray - a fully accessible array of 32-bit numeric entries; can be pre-initialized by specifying a /BuildCharArray array in the Private dictionary, and the size can be controlled via a /lenBuildCharArray entry of type "number".
Most instructions are encoded with a single byte, with the exception of some immediate numbers and the "escape" instructions. The entirety of operators can be divided into six groups depending on their functions:
Byte range 0 - 31:
- Commands for starting and finishing a character's outline,
- Path construction commands,
- Hint commands,
- Arithmetic commands,
- Subroutine commands.
Byte range 32 - 255:
- Immediate values pushed on the operand stack, encoded with a varying number of bytes depending on the size of the number.
All instructions documented in the latest version of the Type 1 format specification are shown in Figure 5.
Figure 5. Currently documented Charstring commands (source: Adobe Type 1 Font Format, Adobe Systems Inc.)
While the current list of Type 1 instructions seems rather short, it is important to remember that the PostScript font formats have been evolving over decades, going through a number of iterations which introduced and removed various operators along the way. As a result, font engines which are supposed to maintain backwards compatibility with most/all fonts ever created likely support instructions that are not on the above list (but may still be interesting from a security point of view). In this context, old revisions of said specifications may be a very valuable source of information.
The Type 1 font specification discusses a number of interesting mechanisms used by the format (such as subroutines or so-called "othersubrs"), but since they are not necessary to understand or exploit the BLEND vulnerability covered in this post, we will not explain them here. If you're interested in font internals or other vulnerabilities discovered during my Charstring security research, we encourage you to study the full specification.
OpenType font primer
The following two documents should work as solid foundation for any OpenType/CFF related research:
Since OpenType is a fully binary format, it's similarly inconvenient to inspect or modify manually. In this case, you can use the ttx.py tool (part of the Fonttools suite) to convert TrueType and OpenType fonts to a human-readable XML form and back. The fact that it supports a majority of modern SFNT tables and TrueType/PostScript programs makes it a very useful tool.
Overall, the OpenType/CFF format is largely similar to Type 1. There are only a handful of major differences:
- the font is always contained within a single file (.OTF) instead of two or more.
- previously textual data (such as some of the Dictionaries) is now encoded in binary form in order to reduce memory/disk consumption.
- the Charstring specification was greatly extended, introducing many new instructions and deprecating some older ones.
A full listing of Type 2 Charstring operators defined in the latest revision of the specification is shown in Figure 6.
Figure 6. All currently documented Type 2 Charstring operators (source: The Type 2 Charstring Format, Adobe Systems Inc.)
A careful reader will notice that the encodings of Type 1 and Type 2 Charstring instructions are binary compatible: the now-unused Type 1 operators are always marked as "-Reserved-" and never reused in Type 2, while all new commands use previously vacant opcodes (either in the main or "escape" namespace). This makes it possible to create a PostScript program containing instructions from both Type 1 and Type 2 specs, which might have been intentional, so that Type 1 and OpenType/CFF fonts could be converted to each other without information loss. However, this behavior might also have some interesting security implications – something to keep in mind for the future.
If we look closely at the list above, we can see that a number of seemingly interesting instructions were added:
- with new global and local type subroutines in OpenType, a callgsubr instruction was introduced,
- hinting-related instructions (hstemhm, hintmask, cntrmask, ...),
- arithmetic and logic instructions (and, or, not, abs, add, sub, neg, ...),
- miscellaneous instructions (random),
- instructions operating on the transient array (get, put).
On the other hand, the "OtherSubrs" functionality was dropped and the callothersubr instruction removed. The execution environment didn't fundamentally change as compared to Type 1 – it still consists of an instruction stream, operand stack (extended from 24 to 48 entries) and a transient array (converted to a fixed-size array of 32 items).
One other interesting part of the CFF specification is a table defining the various limits of data structures used to implement CFF font support (Figure 7). It is a great starting point for auditing any implementation of the format, as it explicitly indicates the places where things can go wrong due to some of these limits not being properly enforced.
Figure 7. Implementation limits of Type 2 Charstring interpreters (source: The Type 2 Charstring Format, Adobe Systems Inc.)
Armed with some general knowledge of the Type 1 / OpenType formats and the Charstring execution environment, let's dive into the Adobe Type Manager Font Driver, which is one of the most complete implementations among PostScript font engines, and is still used in the Windows kernel to rasterize fonts in the operating system.
Adobe Type Manager Font Driver
The ATMFD.DLL library is a third-party Windows kernel module provided by Adobe, which handles all Type 1 and OpenType fonts loaded via the GDI interface. It is based on Adobe Type Manager, a family of programs developed by Adobe alongside the PostScript font specification, used to manage fonts, rasterize them on computer monitors and print text on non-PostScript printers. ATM was available for Windows starting with Windows 3.0 as an optional component, and was first shipped by default in Windows 2000. For the last 15 years, the module has always been there, supporting PostScript fonts in the Windows environment.
In order to make use of ATMFD.DLL, Microsoft introduced a universal interface for installing external font drivers through the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Font Drivers registry key. To our current knowledge, the only value residing there in any default Windows installation is "Adobe Type Manager"="atmfd.dll", and we are not aware of any other third-party font drivers in existence. However, it should be theoretically possible to develop and plug a custom driver supporting any font format we would wish.
When one starts looking into the internals of ATMFD, one thing becomes immediately clear – as opposed to a majority of Windows libraries, this one doesn't have debug symbols available from the Microsoft symbol server. This makes it considerably more difficult to do any reverse-engineering from the start, and might also be one of the reasons why the TrueType font handling implemented in win32k.sys (Microsoft's component) is arguably more thoroughly audited. In order to (partly) work around the problem, we can make use of the fact that function symbols are available for the OpenType implementations found in DirectWrite (DWrite.dll) and Windows Presentation Foundation (PresentationCFFRasterizerNative_v0300.dll). By cross-diffing either of these modules with ATMFD.DLL, it is possible to recover the names of some functions, which might subsequently help with further analysis.
Quite interestingly, there is also another approach to the problem of missing symbols. As Halvar Flake noticed, some ancient builds of Adobe Reader (the ones we know about are Reader 4 for AIX and Reader 5 for Windows) shipped with debug symbols, including the CoolType.dll font processing library. As the code has not fundamentally changed since then, it is also possible to use the old CoolType as a source of symbols which can be matched with modern ATMFD.DLL code; or better yet, all three pieces of software sharing the same common ancestor as ATMFD (DirectWrite, WPF, CoolType) could be used together to get the most complete picture of the reverse engineered module.
There are also other sorts of information included in the Adobe Type Manager which can help us find our way in the assembly – the font driver is full of debug messages which contain a variety of information, like local/global variable names, function names, expressions used in the code and source file paths. Additionally, we can also find a number of string literals related to Type 1 fonts (e.g. names of dictionary fields) which reveal the locations of functions dealing with those entries through their cross-references in the DLL. Examples of such useful strings are shown below:
... and many others. All this information makes it relatively easy to spot the target we are after in this research - the Charstring processing routine - as it directly references many such Charstring related debug strings:
Incidentally, the function is also by far the largest one in the DLL file, with a size of more than 20kB, while the second largest routine is "only" 4kB long. The magnitude and complexity of the function is best illustrated by a control flow graph, as presented in Figure 8. In order to display the graph, the maximum number of nodes in IDA had to be increased from the default value of 1000.
Figure 8. Control flow graph representation of the Charstring processing function found in ATMFD.DLL.
We can further confirm that this is in fact the desired function by using the methods discussed above to acquire its name from one of the libraries with available symbols. If we look into DirectWrite or Windows Presentation Foundation, we will learn that the caller of the function is named "Type1InterpretCharString"; in CoolType, the function itself is called "DoType1InterpretCharString", affirming that this in fact the piece of code we want to look into.
As indicated by the shape and structure of the above graph, we can deduce that the routine most likely consists of a giant switch/case construct, handling each of the various supported PostScript operators accordingly. A deeper analysis of the function shows that this is in fact the case – during each iteration of the execution loop, the function fetches the next command opcode and enters a corresponding block of code:
BYTE op = *charstring++;
switch (op) {
case HSTEM:
case VSTEM:
case VMOVETO:
BYTE op = *charstring++;
switch (op) {
case HSTEM:
case VSTEM:
case VMOVETO:
However, this construct alone doesn't justify the size of the function. In part, it is caused by the fact that it is a universal interpreter used for both Type 1 and Type 2 Charstrings, which are binary compatible formats as mentioned above. This already bodes well for an attacker, as it enables Type 1 Charstrings to make use of all Type 2 (OpenType/CFF) features and vice versa – for example, if there was a vulnerability in a Type 1 specific operator (unrelated to the general structure of Type 1 fonts), an exploit for the vulnerability could also be delivered via an OpenType file, which might sometimes be more convenient for an attacker (.OTF being the more widespread and generally trusted file format).
Further inspection also shows the real reason for the bloated interpreter – it implements every single feature that has ever been part of the Type 1 or Type 2 specifications, including the strictly experimental ones or those officially deprecated many years ago. As the formats have been evolving for decades, the currently officially supported Charstring commands are only a small subset of the entirety of the operators that have ever seen daylight. While presumably done to maintain compatibility with all fonts in existence (including ones created many years ago), this situation is also favorable to a vulnerability hunter, since:
- it significantly increases the attack surface open for analysis and exploitation,
- the implementations of legacy or deprecated features that have not been heard of for a long time are frequently affected by security vulnerabilities, as other developers or researchers might have not been aware of the "hidden" functionality, which may thus have remained untested for many years.
The last noteworthy discovery I made while delving into the interpreter was that the PostScript operand stack (with a maximum of 48 32-bit elements) was implemented in the form of a local array on the interpreter's function stack, and called "op_stk" according to various debug messages referring to it. The current position on the stack was indicated by a local pointer called "op_sp", which would be originally set to &op_stk[0], and then incremented or decremented depending on the executed PostScript commands. While this isn't a bug or bad behavior in itself, it makes it easy for the developer to slip, as somewhat advanced pointer arithmetic needs to be employed to correctly performs all bounds checks affecting the value of "op_sp" – and if one of such checks is missing or faulty, the consequences of having an out-of-bounds operand stack pointer pointing somewhere on the local thread's stack while executing subsequent Charstring instructions might have catastrophic consequences for the security of the affected software. However, let's not jump the gun. :-)
All of the above kept my hopes high for some interesting discoveries – and, as shown at the top of the post, I didn't end up disappointed. In the following section, I will discuss my most impactful finding, the BLEND vulnerability, which provided a primitive allowing for a complete and fully reliable bypass of all currently available software exploit mitigations, and affected both Adobe Reader and the Windows Kernel (ATMFD.DLL) at the same time. Read on.
The BLEND vulnerability (CVE-2015-0093, CVE-2015-3052)
In order to understand the vulnerability being the main subject of the post, we first have to get a grasp on the functionality it was discovered in – the "blend" PostScript operator. It is strongly related to the forgotten Multiple Masters font extension, and was originally introduced in the "The Type 2 Charstring Format" document on 5 May 1998. It was the time when "Multiple Masters" - originally an extension of Type 1 PostScript fonts - was also considered as an addition to the new OpenType/CFF format, resulting in a number of MM-related operators added to the 1998 revision of the Charstring specification (together with new fields introduced into the CFF format). However, since the idea of OpenType/MM was not widely adopted (with just a few such fonts ever coming into existence, none of the publicly used), all references to Multiple Masters were soon removed from the document on 16 March 2000, as shown in the excerpt in Figure 9.
Figure 9. An excerpt from the change log of the "The Type 2 Charstring Format" document from 16 March 2000.
Less than two years of the feature's existence already warranted it a place in the Charstring interpreter found in the Windows kernel and Adobe Reader.
The details of the operation performed by the instruction are explained in the Type 2 Charstring specs from 1998. From a security perspective, the outcome of executing a "blend" operator boils down to the following actions:
- Loading a signed 16-bit integer value from the operand stack (let's call it n).
- Loading k*n further elements from the stack, where k is the number of the font's master designs (2-16, controlled via the length of the /WeightVector Type 1 table).
- Pushing n values back to the operand stack.
In other words, the instruction "blends" k*n values into n numbers on the PostScript stack, with k being a controlled small number and n being an arbitrary 15-bit number with sign. With such complex functionality, involving shifting the stack pointer in various directions based on the result of an arithmetic operation where factors are user-controlled, a number of things can obviously go wrong. The authors of the code were definitely aware of this too, as they included a number of sanity checks executed prior to performing any actual operations on the operand stack:
- Is the stack pointer within the bounds of the operand stack?
op_sp >= op_stk && op_sp <= &op_stk_end - Is there at least one item on the operand stack (the n value)?
op_sp >= &op_sp[1] - Are there at least k*n items on the operand stack to load?
&op_stk[n * master_designs] <= op_sp - Is there enough space left on the stack to push the output parameters?
master_designs != 0 || &op_sp[n] < &op_stk_end
The checks were also made easier to understand thanks to a number of debug messages referenced in the code:
"stack underflow in cmdBLEND",
"stack overflow in cmdBLEND"
"DoBlend would underflow operand stack", "op_stk + inst->lenWeightVector*nArgs <= op_sp"
While the developers went to some great lengths to make sure that the operation would be safe, they missed one corner case: a negative value of n, which is the culprit of the vulnerability. In such case, the control flow reaches a "DoBlend" function, which is where the actual blending operation is performed. If we disregard the specific values loaded from and pushed to the stack, then the only thing the routine does is perform the following operation on the operand stack pointer:
op_sp -= n * (master_designs - 1) * 4
which is a different way of expressing the popping of k*n values, and pushing n values back. In fact, the "DoBlend" function is fortunately constructed such that for a negative n, no actual popping/pushing takes place, avoiding unnecessary corruption of the stack data; however, the "op_sp" pointer is still adjusted accordingly to the formula above. This means that with a controlled 16-bit n, we can increase the stack pointer arbitrarily beyond the "op_stk" array. Since having "op_sp" always point to inside of "op_stk" is one of the fundamental assumptions made by the interpreter code, it is also a security boundary which can be crossed with a sufficiently small negative n number.
It should be noted that while the "blend" operator was documented as part of the Type 2 Charstring specs (used in OpenType files), nowadays it is only functional in the context of Type 1 fonts. This is due to the fact that the number of master designs (referred to as the k factor) can only be controlled via the length of the /WeightVector array in the Top DICT of Type 1 fonts, as the corresponding CFF entries are no longer supported by ATMFD. Hence, the vulnerability is limited to Type 1 fonts only.
It turns out that the rest of the code continues to work in the attacker's favor. Once we execute the "blend" instruction which increases "op_sp" beyond the end of "op_stk", another iteration of the interpreter loop takes place, which starts with the following lines of code:
if (op_sp < op_stk) {
4475, "underflow of Type 1 operand stack",
"op_sp >= op_stk");
if (op_sp < op_stk) {
4475, "underflow of Type 1 operand stack",
"op_sp >= op_stk");
That's right – at the beginning of each instruction's execution, the function checks that "op_sp" is not below the operand stack array, but at the same time doesn't verify the upper boundary, making it possible for the Charstring to continue normal execution with an inconsistent state of the interpreter (an out-of-bounds stack pointer).
Considering that there are two factors of the product used to shift the operand stack pointer (n and k), the maximum number of bytes we can increase "op_sp" by is 32768 (maximum negative value of n) times 15 (maximum number of k - 1) times 4 (size of a single stack item) = 1966080 (0x1E0000), or almost 2MB. Since the exploited thread's stack will probably always be smaller than that, it would allow us to operate on other types of nearby memory regions such as heaps/pools, executable images etc. On the other hand, with k=2, the stack pointer is shifted by exactly -n*4 bytes (-n DWORDs), which provides a great granularity for out-of-bounds memory access. By using a simple two-command "-x BLEND" instruction sequence, we can set "op_sp" to any 4-byte aligned offset relative to the "op_stk" array!
The impact of the vulnerability in the context of ATMFD.DLL can be easily illustrated by using a short stream of four Charstring instructions, which perform the following actions:
- Shift the operand stack pointer so that it points at the interpreter function's return address.
- Trigger an "exchange" operation, swapping the two topmost operand stack entries, which in this case are the stack frame pointer (saved EBP) and the return address.
- Use the ENDCHAR command to cause the control flow to leave the interpreter, thus triggering a bugcheck upon an attempt to execute data from stack while using the corrupted return address.
This process is also shown in the animation below:
And the resulting kernel crash would look as follows:
ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY (fc)
An attempt was made to execute non-executable memory. The guilty driver
is on the stack trace (and is typically the current instruction pointer).
When possible, the guilty driver's name (Unicode string) is printed on
the bugcheck screen and saved in KiBugCheckDriver.
Arg1: 97ebf6a4, Virtual address for the attempted execute.
Arg2: 11dd2963, PTE contents.
Arg3: 97ebf56c, (reserved)
Arg4: 00000002, (reserved)
An attempt was made to execute non-executable memory. The guilty driver
is on the stack trace (and is typically the current instruction pointer).
When possible, the guilty driver's name (Unicode string) is printed on
the bugcheck screen and saved in KiBugCheckDriver.
Arg1: 97ebf6a4, Virtual address for the attempted execute.
Arg2: 11dd2963, PTE contents.
Arg3: 97ebf56c, (reserved)
Arg4: 00000002, (reserved)
The impact of the vulnerability is greatly elevated by the fact that we can use all implemented operators (arithmetic, storage, etc.) over the out-of-bounds "op_sp" pointer, making it possible to add, subtract, move data around the stack, insert constants and so on. In other words, it provides us with all the primitives necessary to build a full ROP chain used to achieve arbitrary code execution. This, in turn, enables the creation of a 100% reliable exploit subverting all modern exploit mitigations such as stack cookies, DEP, ASLR or SMEP. The entire exploitation process takes place during Charstring execution, and therefore doesn't require any interaction with the vulnerable software other than loading a specially crafted font.
The only downside of the bug is that it doesn't affect 64-bit platforms. This is caused by one of the bounds checks in the "blend" operator implementation, which does in fact prevent negative values of n from passing through, thanks to a subexpression being cast to a 32-bit unsigned integer value before being added to a 64-bit pointer:
if ((uint64)(&op_stk + 4 * (uint32)(n * master_designs)) > op_sp)
The behavior effectively eliminates the vulnerability from the compiled code – however, there isn't so much to worry about from the exploitation angle. At the time of this writing, Adobe only ships 32-bit builds of Reader, making all unpatched installations of the software affected by the flaw. While x64 builds of the Windows kernel might be more troublesome, other vulnerabilities discovered during the research could be used to escape the sandbox in our proof of concept exploit, which will also be discussed later in the series.
That's it for today. In the subsequent upcoming posts, we will discuss the process of developing a universal, fully reliable proof-of-concept PDF file, which will spawn an elevated calc.exe running with high integrity level and the "System" security token when opened with the most recent vulnerable versions of Adobe Reader and Windows 8.1 32/64-bit.


text:
Unity and Variety. 1Now in regard to spiritual gifts, brothers, I do not want you to be unaware. 2* You know how, when you were pagans, you were constantly attracted and led away to mute idols.a 3Therefore, I tell you that nobody speaking by the spirit of God says, "Jesus be accursed." And no one can say, "Jesus is Lord," except by the holy Spirit.b
4* There are different kinds of spiritual gifts but the same Spirit;c 5there are different forms of service but the same Lord; 6there are different workings but the same God who produces all of them in everyone. 7To each individual the manifestation of the Spirit is given for some benefit. 8To one is given through the Spirit the expression of wisdom; to another the expression of knowledge according to the same Spirit;d 9to another faith by the same Spirit; to another gifts of healing by the one Spirit; 10to another mighty deeds; to another prophecy; to another discernment of spirits; to another varieties of tongues; to another interpretation of tongues.e 11But one and the same Spirit produces all of these, distributing them individually to each person as he wishes.f
One Body, Many Parts.* 12As a body is one though it has many parts, and all the parts of the body, though many, are one body, so also Christ.g 13For in one Spirit we were all baptized into one body, whether Jews or Greeks, slaves or free persons, and we were all given to drink of one Spirit.h
14Now the body is not a single part, but many. 15If a foot should say, "Because I am not a hand I do not belong to the body," it does not for this reason belong any less to the body. 16Or if an ear should say, "Because I am not an eye I do not belong to the body," it does not for this reason belong any less to the body. 17If the whole body were an eye, where would the hearing be? If the whole body were hearing, where would the sense of smell be? 18But as it is, God placed the parts, each one of them, in the body as he intended. 19If they were all one part, where would the body be? 20But as it is, there are many parts, yet one body. 21The eye cannot say to the hand, "I do not need you," nor again the head to the feet, "I do not need you." 22Indeed, the parts of the body that seem to be weaker are all the more necessary, 23and those parts of the body that we consider less honorable we surround with greater honor, and our less presentable parts are treated with greater propriety, 24whereas our more presentable parts do not need this. But God has so constructed the body as to give greater honor to a part that is without it, 25so that there may be no division in the body, but that the parts may have the same concern for one another. 26If [one] part suffers, all the parts suffer with it; if one part is honored, all the parts share its joy.
Application to Christ.* 27Now you are Christ's body, and individually parts of it.i 28Some people God has designated in the church to be, first, apostles;* second, prophets; third, teachers; then, mighty deeds; then, gifts of healing, assistance, administration, and varieties of tongues.j 29Are all apostles? Are all prophets? Are all teachers? Do all work mighty deeds? 30Do all have gifts of healing? Do all speak in tongues? Do all interpret? 31Strive eagerly for the greatest spiritual gifts.
The Way of Love. But I shall show you a still more excellent way.
* [12:1–14:40] Ecstatic and charismatic activity were common in early Christian experience, as they were in other ancient religions. But the Corinthians seem to have developed a disproportionate esteem for certain phenomena, especially tongues, to the detriment of order in the liturgy. Paul's response to this development provides us with the fullest exposition we have of his theology of the charisms.
* [12:2–3] There is an experience of the Spirit and an understanding of ecstatic phenomena that are specifically Christian and that differ, despite apparent similarities, from those of the pagans. It is necessary to discern which spirit is leading one; ecstatic phenomena must be judged by their effect (1 Cor 12:2). 1 Cor 12:3 illustrates this by an example: power to confess Jesus as Lord can come only from the Spirit, and it is inconceivable that the Spirit would move anyone to curse the Lord.
* [12:4–6] There are some features common to all charisms, despite their diversity: all are gifts (charismata), grace from outside ourselves; all are forms of service (diakoniai), an expression of their purpose and effect; and all are workings (energēmata), in which God is at work. Paul associates each of these aspects with what later theology will call one of the persons of the Trinity, an early example of "appropriation."
* [12:12–26] The image of a body is introduced to explain Christ's relationship with believers (1 Cor 12:12). 1 Cor 12:13 applies this model to the church: by baptism all, despite diversity of ethnic or social origins, are integrated into one organism. 1 Cor 12:14–26 then develop the need for diversity of function among the parts of a body without threat to its unity.
* [12:27–30] Paul now applies the image again to the church as a whole and its members (1 Cor 12:27). The lists in 1 Cor 12:28–30 spell out the parallelism by specifying the diversity of functions found in the church (cf. Rom 12:6–8; Eph 4:11).
* [12:28] First, apostles: apostleship was not mentioned in 1 Cor 12:8–10, nor is it at issue in these chapters, but Paul gives it pride of place in his listing. It is not just one gift among others but a prior and fuller gift that includes the others. They are all demonstrated in Paul's apostolate, but he may have developed his theology of charisms by reflecting first of all on his own grace of apostleship (cf. 1 Cor 3:5–4:14; 9:1–27; 2 Cor 2:14–6:13; 10:1–13:30, esp. 1 Cor 11:23 and 12:12).
b. [12:3] Rom 10:9; 1 Jn 4:2–3.
c. [12:4] Rom 12:6; Eph 4:7, 11.
e. [12:10] 14:5, 26, 39; Acts 2:4.
g. [12:12] 10:17; Rom 12:4–5; Eph 2:16; Col 3:15.
h. [12:13] Gal 3:28; Eph 2:13–18; Col 3:11 / Jn 7:37–39.
Copyright 2019-2024 USCCB, please review our Privacy Policy

subset: commoncrawl


text:
The White House President George W. Bush |
Print this document |
For Immediate Release
Office of the Press Secretary
May 15, 2006
Fact Sheet: Comprehensive Immigration Reform
President Bush Addresses the Nation on Immigration Reform
In Focus: Immigration
Tonight, President Bush Discussed His Vision For Comprehensive Immigration Reform. The five clear objectives of comprehensive immigration reform are securing our borders, creating a temporary worker program, making it easier for employers to verify employment eligibility and continuing to hold them to account for the legal status of workers they hire, dealing with the millions of illegal immigrants who are already here, and honoring the great American tradition of the melting pot.
The President Believes America Can Be A Lawful Society And A Welcoming Society At The Same Time. We will fix the problem of illegal immigration, and we will deliver a system that is secure, orderly, and fair.
1. The United States Must Secure Its Borders
Securing Our Borders Is The Basic Responsibility Of A Sovereign Nation And An Urgent Requirement Of Our National Security. President Bush's proposals to better secure our borders include increasing the number of Border Patrol agents, using enhanced border security technology, ending the practice of "catch and release" along the southern border, eliminating bureaucratic obstacles to returning illegal immigrants to their home countries, and working with our Nation's Governors to send National Guard members to the border for temporary assignment to assist the Border Patrol during the transition as new Border Patrol agents are added and new technologies come online.
Since President Bush Took Office, We Have Increased Funding For Border Security By 66 Percent And Expanded The Border Patrol From About 9,000 To 12,000 Agents. Over the past five years, we have apprehended and sent home more than 6 million people entering America illegally.
The President's Secure Border Initiative (SBI) Is The Most Technologically Advanced Border Enforcement Initiative In American History. This year, we will begin a comprehensive program to construct high-tech fences in urban corridors and build new patrol roads and barriers in rural areas. We will employ motion sensors, infrared cameras, and unmanned aerial vehicles to detect and prevent illegal crossings. We will better integrate our homeland security forces to dramatically improve the efficiency and effectiveness of our border security efforts.
President Bush Is Asking Congress For $327 Million To Help End The Policy Of "Catch And Release." More than 85 percent of the illegal immigrants apprehended at the southern border are from Mexico, and most are returned within 24 hours. For many years, government detention facilities did not have enough beds for many non-Mexican illegal immigrants caught at the border. As a result, most were released back into society. They were each assigned a court date, but the vast majority did not show up.
We Are Working Closely With State And Local Law Enforcement To Stop Illegal Immigration.
The United States And Mexico Are Engaging In Renewed Discussions On Collaborative Border Security And Safety Initiatives. The United States and Mexico have a shared interest in addressing violence against law enforcement personnel and innocent people and increased lawlessness that is occurring in some border areas.
President Bush Is Calling On Congress To Provide Funding For Improvements In Manpower And Technology And Better Collaboration With State And Local Law Enforcement Officials.
We Will Continue Expanding The Federal Government's Partnership With Border Counties And Targeted States. Targeted training and grant programs like the 287(g) program and Operation Stonegarden allow State and local law enforcement to assist the Border Patrol in helping the Federal government quickly expand border security efforts on a temporary basis.
To Help During This Period Of Transition And In Coordination With Governors, Up To 6,000 National Guard Members Will Be Sent To Our Southern Border. The Department of Homeland Security will remain in the lead. National Guard units will assist the Border Patrol by operating surveillance systems, analyzing intelligence, installing fences and vehicle barriers, building patrol roads, and providing training. National Guard units deployed to our border will not be involved in direct law enforcement activities - that duty will be done by the Border Patrol.
The United States, Canada And Mexico Have A Common Border Security Workplan Under The Security Pillar Of The Security And Prosperity Partnership (SPP) Of North America. When the three leaders met in Cancun, Mexico, in March 2006, they committed to working together on a "North American Smart, Secure Borders Plan," which includes close coordination on screening of goods and people, collaboration and prioritization of border infrastructure and technology investment, and concerted law enforcement cooperation to respond to criminal or terrorist threats.
2. To Secure Our Border, We Must Create A Temporary Worker Program
President Bush Supports A Temporary Worker Program That Would Create A Legal Path For Foreign Workers To Enter Our Country In An Orderly Way, For A Limited Period Of Time. This program would match willing foreign workers with willing American employers for jobs Americans are not doing. Every worker who applies for the program would be required to pass criminal background checks, and temporary workers must return to their home country at the conclusion of their authorized stay.
3. We Need To Hold Employers To Account For The Workers They Hire
Comprehensive Immigration Reform Must Include The Creation Of A New Identification Card For Every Legal Foreign Worker So Businesses Can Verify The Legal Status Of Their Employees. This card should use biometric technology to make it tamper-proof. A tamper-proof card would help us enforce the law - and leave employers with no excuse for violating it. We will also work with Congress to expand "basic pilot" - an electronic employment verification system - and mandate that all employers use this system to quickly and accurately confirm work eligibility for all prospective employees. By making it harder for illegal immigrants to find work in our country, we would discourage people from crossing the border illegally in the first place.
4. We Must Deal With The Millions Of Illegal Immigrants Who Are Already Here
Illegal Immigrants Should Not Be Given Amnesty. President Bush opposes amnesty and believes illegal immigrants should not be given an automatic path to citizenship because it would be unfair to those who are here lawfully and would invite further waves of illegal immigration. The President supports increasing the annual number of green cards that can lead to citizenship, but for the sake of justice and security, the President is firmly opposed to amnesty.
President Bush Believes That Deporting Every Illegal Immigrant Is Neither Wise Nor Realistic. There is a rational middle ground between granting an automatic path to citizenship for every illegal immigrant and a program of mass deportation.
President Bush Believes Illegal Immigrants Who Have Roots in America And Who Want To Stay Should Have To Pay A Meaningful Penalty For Breaking The Law, Pay Their Taxes, Learn English, And Work In A Job For A Number Of Years. The President also believes that there are differences between an illegal immigrant who crossed the border recently - and someone who has worked here for many years, and has a home, a family, and an otherwise clean record. Those who meet our conditions should be able to apply for citizenship - but approval will not be automatic, and they will have to wait in line behind those who played by the rules and followed the law.
5. We Must Honor The Great American Tradition Of The Melting Pot
The Success Of Our Country Depends Upon Helping Newcomers Assimilate Into Our Society And Embracing Our Common Identity As Americans. Americans are bound together by our shared ideals, an appreciation of our history, respect for the flag we fly, and an ability to speak and write the English language.
The House And Senate Must Pass A Comprehensive Immigration Reform Bill
All Elements Of This Problem Must Be Addressed Together - Or None Of Them Will Be Solved At All. The House has passed an immigration bill. The Senate should act by the end of this month - so that the House and Senate can work out their differences and send the President a comprehensive bill to sign.
America Needs To Conduct This Debate In A Reasoned And Respectful Tone. Feelings run deep on the matter of immigration - and as we work out this issue, all of us need to keep some things in mind. We cannot build a unified country by inciting people to anger, or playing on anyone's fears, or exploiting the issue of immigration for political gain. We must always remember that real lives will be affected by our debates and decisions, and that every human being has dignity and value no matter what their citizenship papers say.
# # #


text:
Elsa is a C and C++ parser. It is based on the Elkhound parser generator. It lexes and parses input C/C++ code into an abstract syntax tree. It does some type checking, in the interest of elaborating the meaning of constructs, but it does not (yet?) reject all invalid programs.
To download Elkhound and Elsa, see the Elkhound distribution page.
High-level documentation:
Low-level documentation:
Elsa requires the following external software:
Build instructions:
$ ./configure $ make $ make check./configure understands these options. You can also look at the Makefile.
Parsing some sample (already preprocessed) input:
$ ./ccparse in/t0001.ccThe above command will parse and type check the given file. To make it print the annotated, post-type-check AST, say
$ ./ccparse -tr printTypedAST in/t0001.cc
Additional -tr flags of interest:
Module dependency diagram:
Or, in Postscript.
Miscellanous files:


text:
Art first. Love later…or so she thought.
Sea life sculptor Piper Diaz is tired of being pressured to conform. She is never marrying, joining her family's investment firm, or moving from her tiny industrial loft. Her sole focus is getting her artwork shown. And screw anyone who's told her to drop the hobby. Nothing will stop her now that Pacific Blue Fine Art Gallery has agreed to show her sculptures. Things are finally going her way…
That is until entrepreneur and businessman Alex Hutton purchases the gallery and has zero interest in unknown artists. He gives her a choice to work for him or quit.
Alex has sunk all his money into reimagining Pacific Blue and turning it into a premier gallery. He won't be distracted and certainly not by the beautiful Latina glaring at him. Still, there's something about Piper he just can't shake, regardless of his heart-shattering past. Pacific Blue must open in a month or he loses everything. Working alongside Piper might just cause him to lose his heart along with his investment.
Check it out on Goodreads!
Kristina writes multi-layered stories with characters that stay with readers long after the words The End. Her first work of women's fiction A Forgiving Heart received honorable mention for a novel excerpt in the Soul-Making Keats Literary Competition sponsored by the National League of American Pen Women. Her contemporary romance novels Pleasure Cove and Pacific Blue promise the same emotional read, stunning California settings, along with strong, sassy heroines and heroes who will steal your heart.
A California native, Kristina shares her love of the Golden State with readers through setting and culture in a series of contemporary romance novels. When she isn't writing, she is exploring her state, traveling, looking for the best eats (she's a major foodie), and spending time with her family.


text:
We Recognize Your Privacy
World Racing Group recognizes the importance of protecting the privacy of certain information ("Information") collected about our customers and prospective customers (referred to as "Customers"). This privacy statement discloses what information we gather, how we use it, and how to correct or change it.
To that end, World Racing Group gathers two types of information about Customers: data that Customers provide through optional, voluntary registration on our sites; and data gathered through aggregated tracking, mainly by tallying page views throughout our sites. Such information enables us to tailor our content to fit Customers' needs better and to help our advertisers understand our audience. However, be assured that World Racing Group will not disclose personal Information to third parties without your consent, except as may be noted in this Privacy Policy or disclosed to you when the Information is submitted.
How does World Racing Group collect Information?
- Optional registration
- We collect information by specifically requesting it from you. Generally this occurs when you register at a site or request information or a service.
- Usage tracking
Use of Internet Protocol ("IP") Addresses
An IP address is a unique number that is automatically assigned to your computer whenever you're surfing the Internet so that your computer can be identified by the main computers, known as "Web servers", that "serve up" Web pages.
World Racing Group collects IP addresses for the purposes of system administration, to report aggregated information to our advertisers, and to audit the use of our site. When Customers request pages from xtremeoutlawseries.com, our servers log the Customers' IP addresses. We do not normally link IP addresses to anything personally identifiable, which means that a Customer's session will be logged, but the Customer will remain anonymous to us. We can and will use IP addresses to identify a Customer when we feel it is necessary to enforce compliance with our site terms of use or terms of service or to protect our service, site, customers or others.
Use Of Cookies
What are cookies? Cookies are small pieces of information that a Web site sends to yours computer for record-keeping purposes, which information is stored in a file on your computer. Cookies make Web surfing easier for you by saving your preferences so that we can use the saved information to facilitate your use of our Web site when you return to the site. Cookies do not tell us your individual identity unless you have chosen to provide it to us. We never save passwords or credit card information in cookies. The use of cookies is an industry standard, and as such, you'll find that most major Web sites use them.
By showing how and when Customers use a site, cookies help us see which areas are popular and which are not. Many improvements and updates to the site are based on such data as total number of visitors and pages viewed. This information is most easily tracked with cookies. We use the information from cookies to provide services better tailored to our Customers' needs.
Most cookies expire after a defined period of time, or you can delete your cookie file at any time. Most browsers are initially set up to accept cookies. You can reset your browser to refuse all cookies or indicate when a cookie is being sent. However, note that some parts of xtremeoutlawseries.com will not function properly or may be considerably slower if you refuse cookies. For example, without cookies, you will not be able to set personalized preferences, and/or may have difficulty completing marketing transactions.
World Racing Group has two primary uses for its cookies. First, we use them to specify a Customer's preferences. Second, we use cookies to track Customers' Web site usage trends and patterns. This helps us understand our Customers' needs better and improve areas of services that our Customers find valuable. While both of these activities depend on the use of cookies, you have the option of disabling the cookies via your browser preferences.
With whom does World Racing Group share my Information?
World Racing Group will not disclose any specific personal information that you submit to us about you ("Personal Information") in a manner that connects you with the Personal Information, except when we have your permission.
Business Partners & Sponsors: World Racing Group may disclose some or all of your Personal Information to business partners or sponsors, but this use will be specifically described to you prior to data collection or prior to transferring the data. Many promotions offer opportunities to request additional information from sponsors. By requesting more information, you give World Racing Group permission to transfer your Personal Information to the sponsor so they can fulfill your request. In many instances, only your e-mail address will be shared. If more Personal Information will be shared with the sponsor, you will be notified prior to the transfer.
Third Party & Aggregate Data: From time to time, you may be offered the opportunity to receive materials or special offers from third parties. If you opt to receive information from these third parties, World Racing Group will (with your permission) share your name and e-mail address with such third parties.
Other: World Racing Group may also disclose account Information in special cases when we have reason to believe that disclosing this Information is necessary to identify, contact or bring legal action against someone who may be violating World Racing Group's Terms of Use.
How can you control the usage of Information?
In case you change your mind or some Personal Information changes (such as your zip code or e-mail address), we will try to provide a way to correct, update or remove the Personal Information that you give us. We also give you the opportunity to control the communications we direct to you.
What happens when you link to a third party site?
You should be aware that when you are on xtremeoutlawseries.com you could hyperlink or be directed to other sites that are beyond our control and/or outside our service. These other sites may include sites of advertisers, sponsors and partners that may use World Racing Group's logo as part of a co-branding agreement. These other sites may send their own cookies to Customers, collect data, or solicit Information.
World Racing Group does not control such sites, and, therefore, is not responsible for their contents or the hyperlinks or advertising they choose to place on such sites. World Racing Group's inclusion of hyperlinks to these sites do not imply any endorsement of the material on such sites or any association with their operators.
Please keep in mind that whenever you give out information online (for example, via message boards or chat) that information can be collected and used by people you don't know. While World Racing Group strives to protect its Customers' information and privacy, we cannot guarantee the security of any information you disclose online, and you disclose such information at your own risk.
By using this site, you signify your agreement to World Racing Group's Privacy Policy. IF YOU DO NOT AGREE WITH THIS POLICY, PLEASE DO NOT USE THIS SITE. Your continued use of xtremeoutlawseries.com following the posting of changes to these terms will mean you accept those changes.


text:
In the early 1950s, archaeologists unearthed several clay tablets from the 14th century BCE. Found, WFMU tells us, "in the ancient Syrian city of Ugarit," these tablets "contained cuneiform signs in the hurrian language," which turned out to be the oldest known piece of music ever discovered, a 3,400 year-old cult hymn. Anne Draffkorn Kilmer, professor of Assyriology at the University of California, produced the interpretation below in 1972. (She describes how she arrived at the musical notation—in some technical detail—in this interview.) Since her initial publications in the 60s on the ancient Sumerian tablets and the musical theory found within, other scholars of the ancient world have published their own versions.
The piece, writes Richard Fink in a 1988 Archeologia Musicalis article, confirms a theory that "the 7‑note diatonic scale as well as harmony existed 3,400 years ago." This, Fink tells us, "flies in the face of most musicologists' views that ancient harmony was virtually non-existent (or even impossible) and the scale only about as old as the Ancient Greeks."
Kilmer's colleague Richard Crocker claimed that the discovery "revolutionized the whole concept of the origin of western music." So, academic debates aside, what does the oldest song in the world sound like? Listen to a midi version below and hear it for yourself. Doubtless, the midi keyboard was not the Sumerians instrument of choice, but it suffices to give us a sense of this strange composition, though the rhythm of the piece is only a guess.
Kilmer and Crocker published an audio book on vinyl (now on CD) called Sounds From Silence in which they narrate information about ancient Near Eastern music, and, in an accompanying booklet, present photographs and translations of the tablets from which the song above comes. They also give listeners an interpretation of the song, titled "A Hurrian Cult Song from Ancient Ugarit," performed on a lyre, an instrument likely much closer to what the song's first audiences heard. Unfortunately, for that version, you'll have to make a purchase, but you can hear a different lyre interpretation of the song by Michael Levy below, as transcribed by its original discoverer Dr. Richard Dumbrill.
Note: An earlier version of this post appeared on our site in 2014. It's old but gold. So we hope you enjoy revisiting it again.
If you would like to sign up for Open Culture's free email newsletter, please find it here. Or follow our posts on Threads, Facebook, BlueSky or Mastodon.
If you would like to support the mission of Open Culture, consider making a donation to our site. It's hard to rely 100% on ads, and your contributions will help us continue providing the best free cultural and educational materials to learners everywhere. You can contribute through PayPal, Patreon, and Venmo (@openculture). Thanks!
Related Content:
What Ancient Greek Music Sounded Like: Hear a Reconstruction That is '100% Accurate'
Hear The Epic of Gilgamesh Read in the Original Akkadian and Enjoy the Sounds of Mesopotamia


text:
Please read this Privacy Policy carefully before using www.shankarmahadevanacademy.org ("Web site"), an Internet site maintained by Shankar Mahadevan Academy Trust. ("SMA Trust"), the operator of Shankar Mahadevan Academy. Your use of the Web site serves as your acceptance of this Privacy Policy and consent to SMA Trust 's collection and use of the information you provide as set forth in the Privacy Policy. Please note that this Privacy Policy applies only to the Web site, and not to other Web sites operated by other companies or organizations to which we may link. When you link to any other Web sites from the Web site, this policy no longer applies and SMA Trust has no control of the activities of those Web sites. Also this Privacy Policy does not apply to any information that SMA Trust may collect from you in any manner other than online.
SMA Trust may revise this Privacy Policy at any time. You should, therefore, review it periodically. If you do not want to submit personal information when requested, you will not be able to access certain areas on our site. However, you do not need to provide personal information to SMA Trust in order to use the Web site.
SMA Trust generally only collects personally identifiable information from you when you voluntarily submit it to us when you: register with us; enroll in online classes; purchase products from any online stores we offer; participate in contests, events or promotions; send us questions or comments via e-mail; and/or, fill out online surveys, or any other requests we make for suggestions or comments about the Web site. This information may include personal information such as your name, e-mail address, telephone number, and home address. Also, we may request certain demographic information such as your age, and gender. We never collect more information than what is reasonably necessary to fulfill your requests and our legitimate business objectives. We will take appropriate steps to ensure the security and integrity of any information you provide to us.
If you are under the age of 13, your parent or guardian's consent is required before you can provide any personal information to us for purposes of registration and/or other online activities.
If we ask you to register with the Web site, we may ask for personal information such as your full name and e-mail address, and mailing address. SMA Trust may use such information to periodically contact you with news, and relevant announcements. SMA Trust may sponsor sweepstakes, contests or other events ("Promotions") which require the collection, processing, and storage of individual contact information plus demographic information. If you want to join in on our Promotions, we may ask you to provide an e-mail address, so that we can let you know if you won a prize. For other SMA Trust promotions, we may request your name and home address in order to send you products or information by regular mail.
SMA Trust collects the personal information you provide on the Web site. We may use the information you submit to the Web site to send you advertising or promotional materials, including information about new contests, features and enhancements, special offers and other events of interest. We also use your personal information for our internal marketing and demographic studies, so we can constantly improve the products and services we provide you and can better meet your needs.
The demographic information (such as age and gender) you provide us is collected by SMA Trust and may be disclosed in aggregate to third parties. This aggregate demographic information cannot be used to personally identify you or your computer.
From time to time, SMA Trust may use and share Web site user's personal information with entities who use it solely to provide support for the internal operations of the Web site (for example, online product fulfillment, e-mail services, or technical support). These entities will not use your personal information for any other purpose, and have agreed to maintain the confidentiality, security, and integrity of the personal information they obtain from us.
We may disclose personal information in the good faith belief that we are required to do so by law, including but not limited to disclosure to law enforcement or other government officials in connection with an investigation of fraud, intellectual property infringements, or other activity that is illegal or may expose you or us to legal liability.
Generally, SMA Trust only uses personal information collected from and about its users for the purpose for which it is submitted, unless we disclose other uses at the time we collect the information. If we do, you will have the opportunity to instruct us not to use your data in other ways (you can "opt-out" – see below). We may sometimes share personally identifiable information with our affiliates or business partners who might like to send you information about their products or services. If you do not want your information used in this manner, you may "opt-out." We sometimes offer Promotions in conjunction with a sponsor, and may share your information with these sponsors. We will identify the sponsor for you, and provide you with the opportunity to "opt-out." In the event of a merger, acquisition, reorganization, bankruptcy, or other similar event, SMA Trust's customer information may be transferred to SMA Trust's successor or assign, if permitted by and done in accordance with applicable law.
Because SMA Trust values all customer relationships, it will not disclose customers' nonpublic personal information to nonaffiliated third parties, except as described in this policy or as otherwise permitted by law. We DO NOT allow any email harvesting. If you feel you have been contacted in error by a party other than SMA Trust please contact SMA Trust email@example.com.
Like most Web sites, SMA Trust uses "cookies" on the Web site. Cookies are pieces of information that we place on your computer to help us accurately understand how many consumers are visiting a particular site, how often they visit that site, and what content they are most interested in. For example, a cookie will allow us to remember certain things based on your Internet Protocol or "IP" address (an IP address is the string of numbers that identifies each sender or receiver of information that is sent across the Internet), such as the time and duration of your visits, how you navigated through our content and where you exited a particular site. This lets us know how many people are coming to individual sites, how frequently, and how they are using the sites, allowing us to make updates to content and improve navigation as appropriate. We cannot tell who you are or where you are. SMA Trust will never use cookies to retrieve information from your computer that SMA Trust did not originally send in a cookie.
To provide relevant information not found on the Web site and to provide a greater variety of online opportunities, SMA Trust may provide links from the Web site to third party web sites. We encourage our Web site visitors to read third party sites' privacy policies before submitting personal information. SMA Trust is not responsible for any information these web sites may obtain from you and we do not review or oversee their privacy policies or procedures.
If you do not want SMA Trust to send you e-mail or regular mail about our products and/or services, you can choose to opt-out and have your name removed from SMA Trust's e-mailing list by using the link included with a SMA Trust e-mail or by sending an e-mail to email@example.com. SMA Trust will occasionally send email announcing changes or enhancements to our site or services. If you do not wish to receive these announcements, please notify email@example.com.
Students enrolled in a course or program with Shankar Mahadevan Academy are automatically opted in to receive all email communications. Most communication between Shankar Mahadevan Academy and its student body is conducted in this manner.
The various emails keep students up to date on:
In order to ensure all students are kept up to date on the happenings of the online school, we need to be able to communicate through email.
You may at any time review and/or update the contact information we have for you or inform us that you want us to remove such information from our database by contacting us at:firstname.lastname@example.com. You must provide us with information on the activities you participated in which requested personal information. Before we can change or delete any information, we require that you provide us with proof of your name and address. Once we receive such proof, we will immediately delete or modify your information and refrain from collecting any other personally identifiable information from you, if you request. Please note, however, that there may be some residual information that may remain in our databases that may or may not contain personally identifiable information. We will not provide this information to any third party, or use it for any commercial purpose.
Consistent with the Children's Online Privacy Protection Act ("COPPA"), SMA Trust does not solicit personal information from children. Visitors 13 years of age and under should remember that they are required to obtain an adult's permission before submitting any personal information to this, or any other, Web site.
If you have any questions about this Privacy Policy, the practices of this Web site, or your dealings with this Web site, please contact email@example.com or by mail:
Clood On Learning Pvt. Ltd.
First Floor, Rathna Building,
143 Richmond Road, Rathna Avenue
Bangalore, India 560025


text:
Tracolla porta cellulare
- Description
Porta cellulare, occhiali, chiavi e documenti.
Zip principale + taschino esterno con bottone.
Tracolla regolabile in tessuto in fantasia.
Contact us directly via our real time chat. Or by email: email@example.com
Does our jewellery fade over time?
No! Our jewellery is made entirely in stainless steel. Its resistance to corrosion is thus optimal. It will not be damaged if you get it wet, therefore, and will lose nothing of its colour or shine. It does NOT leave black marks on the skin and it is hypo-allergenic.
Are your bags genuine leather?
Yes! All our bags are in real MADE IN ITALY leather. Maximum durability and top quality.
How much does delivery cost?
Delivery Italy-wide costs €5 (€7 for the islands) and is free for orders over €100.
How many days do deliveries take?
24/48 hours (working days only) from order acceptance.


text:
Living in the digital era of social media and content creators on peak, you probably have seen several people creating their blogs and using their platforms to inspire, inform, and influence people in a modern method.
While we are no longer limited to diary content, almost everyone is now jumping on the bandwagon and owning blog accounts that feature mostly their personal experiences, entrepreneurship, beauty, and health, as well as stances on societal issues, among other things.
Blogging has already reached its peak. The digital form of a diary or journal has been constantly connecting people with different thoughts and feelings on certain subjects. Bridging the gaps and borders online, this online journal has been serving its purpose. And while others chose to keep their blogs personal, many prefer to share their thoughts with the world through blogging.
Stumbling upon these, many people ask themselves for some time like "is blogging a good idea? Was it worth the time and effort? Does it have standards to meet? Should I start a blog?"
People have several reasons why they chose to create their own blogs. Thus, if you are still skeptical about starting your overdue plan of creating your personal blog, here are some reasons why you should consider starting writing your blog this 2022.
Blogging is a healthy emotional outlet
Looking back to how you teared up and got frustrated over the challenges you faced and how you bottled up your mourning of losing someone or something dear to you, one coping method which helped you was writing what causes you to feel emotional.
Similarly, to how you wrote the best experience and lesson you've learned from someone or something you've gone through. Writing everything from a traditional diary goes exactly accessible to writing them in your blog especially if it's for personal purposes.
Blogging serves as your emotional outlet, your companion, and it can absorb any of your unsaid thoughts and feelings. Studies have shown that writing helps people emotionally after a sad traumatic experience thus, blogging can be used to help lessen emotional hardships in life.
Blogging helps you to be a catalyst of change
This may seem dramatic or overrated to others, but a single blog can certainly create a difference in the lives of other people. Whether your blog focuses on your personal experiences, your health and beauty advice, or anything that is socio-political, there is always a chance that someone who reads your blog/s is experiencing a similar situation or dilemma.
Think about how the blogs of other people you read online influence your thoughts and feelings — the same goes for anyone who will read your content. Whatever your goal upon writing, what's certain is your blog connects to different people with different stories and different perspectives — helping them to try some changes or to decide about something helpful to improve themselves.
Blogging is learning more about yourself
Cliché, as it may sound but writing your own blog, is like giving yourself the chance to explore more of yourself. Every day, we undergo the process of improving and at the same time discovering something new about ourselves. Choosing what to write on every blog is choosing to learn even the littlest of our identities — wanting this or that — being considerate to someone, realizing tastes on something are changing; and any other things that we can learn once we start blogging.
While we do our blogs, we read and write and do the same process a few times helping us to further notice that what we thought we were from the previous days or years has somehow changed over time — noticing the occurring changes and having the somewhat feeling of looking into something different from ourselves.
Blogging exercises humor and creativity
Blogs curated with a sense of humor and creativity are more likely to reach and impress a wide variety of audiences — a fact of blogging. Blogging is a commitment that requires a certain level of a person's humor and creativity which creates a pleasurable writing experience for a blogger and a fun reading experience for its reader.
Sure, you can write on your blog whatever you want but if you do have the goal to reach the public with your content, you will need to put up humor and creativity to your blog.
Remember, the best part of blogging aside from expressing yourself is knowing that readers were inspired to read and share your blog because of the humor and creativity featured in it. This is how most readers convert from silent readers to fully supportive ones because of the fun and rich reading experience.
Blogging opens doors of possibilities
They say there is no such thing as "impossible" in an age when almost anything can be posted online. In the vastness of the digital world, what was posted yesterday may be an opportunity of tomorrow. A single blog may bring something new because published blogs can be read by anyone from anywhere in the world. In some cases, people forget that blogging is more than just a place to express one's thoughts or write about anything under the sun.
Blogging can also be used for business branding, job hunting, and money-making. Blogging has so much to offer, and it certainly is not limited to what other people initially know because, in blogging, you can actually earn, develop transferable skills for future professional endeavors, and it actually helps you get employed by companies who are looking for writing, communication, and critical thinking skills — all enhanced through blogging.
Blogging gives sense of freedom
Today, with all the stress and anxiety brought by the differing responsibilities in and outside our home, we felt like we have been boxed into something that limits us to spend time with ourselves. Our plans and goals tied us to achieve them with our created timeliness that we sometimes forget to breathe — somehow losing the sense of liberty we need to endure. It is what blogging makes one of the most liberating things to do for a person who wants to feel free from the things that cause stress and confines. The opportunity to decide, work and do things you love without minding the pressure of deadlines and expectations from anyone — something that is entirely you who is being you.
In blogging, you are free to talk about your struggles, share your exciting experiences during your travels, the lessons your parents have taught you, the sporting activities you just started, the role you took part in during a community activity, your obsession with a certain brand, your starting business, or your political stance. Everything is on you as blogging gives you the freedom to share anything you want to.
Like anything else in this world, blogging is a process and a commitment one should learn to embrace. Like any other bloggers, they also started from "should I really start my own blog" to actually doing it for a long time now. But what matters to people who want to consider writing a blog and creating a platform for themselves is that blogging isn't a temporary sensation as it requires a long period and effort as long as one desires to continue.
Wanting to share a passion? Educate other people? Gain exposure? In blogging, you have a concrete platform where you can go beyond the ordinary and have the opportunity to create an impact on other people's lives. Starting your own blog is also looking at what it really takes to see yourself in a new field, bringing your values and the things you wanted to write about because blogging can be anyone's start — it can be for anyone.
Find out more of these stories at http://mnlmag.com/ or you can visit http://theluzondaily.com/ for the latest news and updates.


text:
I do not know what I would do if I didn't have an awesome pancake recipe to fall back on when I have no creative juices, my eyes are juuust open, and I haven't even thrown a splash of coffee down the ol' hatch. But today, I had to be a little creative because a) we were out of eggs, b) we were out of sugar, and c) I knew people were going to want an amazing breakfast this morning due to the fact that they were "punished" with oatmeal yesterday.
These pancakes contain chia seeds, possibly the most amazing superfood to grace this planet earth. Chia seeds are full of omega-3's, fiber, phosphorus, manganese, protein, and calcium. AND they help you get full faster, making it easier for those who want to lose weight to do so.
I add chia seeds to everything from granola, smoothies, overnight oatmeal, and, now, pancakes!
Everyone in my family loved the heck out of these pancakes, including me! I had to tell myself three was enough. But I wanted more. Like seven more! But, as we all know, that would not be a very good idea.
I used vegan butter on these pancakes because, ya know, it's a vegan recipe and vegan butter is quite an awesome thing. You can make your own, or buy it from your local health food stores. I also used organic pure maple syrup on top of these pancakes.
In a word, these whole wheat chia seed pancakes are GLORIOUS!
Here's the recipe:
- ¾ cup unbleached all-purpose flour
- ¾ cup white whole wheat flour (where to buy)
- 1 tablespoon baking powder
- 1 teaspoon kosher salt
- 3 tablespoons organic chia seeds (where to buy)
- ½ teaspoon ground cinnamon
- 3 tablespoons organic maple syrup (where to buy)
- 1 teaspoon pure vanilla extract
- 11/2 cups organic rice milk
- 1 teaspoon organic apple cider vinegar
- In a medium bowl, mix together the all-purpose flour, whole wheat flour, baking powder, salt, chia seeds, and cinnamon until combined.
- Add the maple syrup, vanilla extract, rice milk, and apple cider vinegar and stir until just combined.
- Let the batter sit for 5 minutes to thicken up.
- Preheat and lightly grease a griddle or skillet on medium-low heat. Using a measuring cup, pour slightly less than ¼ cup of batter onto the skillet to form each pancake.
- When the pancakes begins to bubble and the edges start to look dry, flip them over and cook the other side. Remove the pancakes from the skillet and serve warm. Top as desired.


text:
This stunning handbag is expertly woven from durable paper straw, ensuring its longevity while adding a touch of eco-consciousness to your fashion ensemble. With its exceptional weaving details, this handbag is a true work of art. Each strand of straw is intricately entwined to create a beautifully textured pattern that sets it apart from ordinary bags. The attention to detail is evident in every stitch, showcasing the skill and craftsmanship of our talented artisans.
- Type: Hand bag
- Bag size: Medium
- Pattern type: Solid
- Material: 100% paper
- Imported
- Product measurements:
One size: 15*17.5 in
Shoulder strap: 10 in
Justin Taylor is a family-owned wholesale company located in LA. They offer trendy outerwear and accessories that complete any look.