进都进来了,不顺手点赞评论么?

【原创】通过PDF攻击溯源

应急响应 Wangyeyu2015 98℃

“PDF是Portable Document Format的简称,意为“可携带文档格式”,是由Adobe Systems用于与应用程序、操作系统、硬件无关的方式进行文件交换所发展出的文件格式。PDF文件以PostScript语言图象模型为基础,无论在哪种打印机上都可保证精确的颜色和准确的打印效果,即PDF会忠实地再现原稿的每一个字符、颜色以及图象。” — — WIKI

近期博主发现有很多黑客组织在攻击时,喜欢额外放一个PDF作为诱饵文档,用来迷惑用户降低用户的警惕性,殊不知,PDF中也存在着多个字段可以协助我们进行溯源。

首先,我们先来认识一下PDF文件,PDF结构分为四个部分,分别是:

  1. header,提供PDF版本号
  2. body ,包含页面,图形内容和大部分辅助信息的主体,全部编码为一系列对象。
  3. xref Table,交叉引用表,列出文件中每个对象的位置便于随机访问。
  4. Trailer,trailer包括trailer字典,它有助于找到文件的每个部分, 并列出可以在不处理整个文件的情况下读取的各种元数据。
我们可以测试一下,就使用Word来生成一个PDF吧,首先打开Word,点击文件。

选择另存为,点击浏览,选择保存类型为PDF、

这样我们就生成了一个PDF文件,如下图

接着,我们使用010Editor 打开PDF(首次打开会提示安装一个PDF模板),我们选择点击“安装”模板

点击同意

此时我们便使用010Editor解析了PDF文件。

我们先简单看一下文件结构,我们展开“struct PDFHeader sPDFHeader”可以看到这个PDF文件遵守的是PDF1.7的规范。

我们接着向下看,找到”PDFObj”中的”Author”对象,可以看到有一部分乱码了,我们定位到到编辑界面去查看。

依次点击“Author”对象所在的”PDFObj[8]”->”Data[200]”,可以看到上面部分的编辑框已经定位到字段位置。

我们可以通过编辑窗看到作者名字是“PC”,使用了“Microsoft Word LTSC”创建了该PDF。

创建的时间是“2022年12月01日11点12分21秒”,时区是“+08:00”。

我们接着往下看,发现还有一个“XML”对象。

我们依旧在编辑器中定位过去,并将其复制出来。

发现我们依旧可以在该字段看到用户、时间、时区、生成软件等信息。


在我们日常的工作中,便可以通过上述方法,对黑客使用的诱饵文档进行分析,并提取其中的关键信息,像是时区、用户名、使用软件等等进行攻击溯源。

PS:补充一点,使用不同软件生成的PDF是会有细微不同的,例如Chrome生成的PDF会附带“UA”信息,其他软件生成PDF也是类似原理。

PPS:博主曾在前些年使用了该方法,溯源到了某黑客团队的,最后,希望大家也能有所收获!

010 Editor – PDF模板解析代码如下:

//------------------------------------------------
//--- 010 Editor Binary Template
//
//      File: PDF.bt
//   Authors: Didier Stevens, Christian Mehlmauer
//   Version: 0.2
//   Purpose: Template for Adobe PDF (Portable Document Format) files.
//  Category: Document
// File Mask: *.pdf
//  ID Bytes: 25 50 44 46 //%PDF
//   History: 
//   0.2   2016-05-19 Christian Mehlmauer: Parsing of XREFs
//   0.1   2016-01-28 SweetScape: Updated header for repository submission.
//   0.0.1 DS: First public release.
//
//	As the PDF file format is not your usual binary file format for which it is easy to create
//	010 templates, I had to resort to unusual template programming techniques.
//	Some limitations of the 010 scripting language (like not being able to create local structures)
//	also explain the unusual style.
//	Summary of the algorithm used by this template:
//		- search for keywords with FindAll (%PDF, %%EOF, obj, endobj): FindAllKeywords()
//		- merge all found keywords into one array, and filter out found keywords that are not actual
//		  PDF structures (like obj without preceding index and version): MergeAndFilterAllKeywords()
//		- loop over all keywords and prepare data needed to create PDF structures: PrepareStructures()
//		- create PDF structures: CreatePDFStructures()
//
//	Source code put in public domain by Didier Stevens, no Copyright
//	https://DidierStevens.com
//	Use at your own risk
//
//	History:
//		2010/08/03: start development with 010 Editor v3.0.6
//		2010/08/04: continue
//		2010/08/05: continue
//		2010/08/06: refactoring, cleanup
//------------------------------------------------

local int iCOLOR = 0x95E8FF; // Color used for highlighting PDF structures

enum int {TYPE_UNKNOWN, TYPE_HEADER, TYPE_TRAILER, TYPE_OBJ, TYPE_ENDOBJ};

// Global variables

local int iKeywordCount;
local int iStructureCount;
local TFindResults tfrHeaders;
local TFindResults tfrTrailers;
local TFindResults tfrObjs;
local TFindResults tfrEndobjs;

local int iPDFHeaderCount = 0;
local int iPDFTrailerCount = 0;
local int iPDFUnknownCount = 0;
local int iPDFCommentCount = 0;
local int iPDFWhitespaceCount = 0;
local int iPDFXrefCount = 0;
local int iPDFObjectCount = 0;

// Structures

local int iIndexLength;
local int iWhiteSpace1Length;
local int iVersionLength;
local int iWhiteSpace2Length;
local int iDataLength;
local int iFoundEndobj;
local int iWhiteSpace3Length;
typedef struct {
	BYTE Index[iIndexLength];
	BYTE WhiteSpace1[iWhiteSpace1Length];
	BYTE Version[iVersionLength];
	BYTE WhiteSpace2[iWhiteSpace2Length];
	BYTE Object[3];
	BYTE Data[iDataLength];
	if (iFoundEndobj)
		BYTE EndObject[6];
	BYTE WhiteSpace3[iWhiteSpace3Length];
} PDFObj <read=ReadPDFObj>;

string ReadPDFObj(PDFObj &sPDFObj)
{
	local string sResult;
	SPrintf(sResult, "%s %s obj %s", sPDFObj.Index, sPDFObj.Version, sPDFObj.Data);
	return sResult;
}

local int iHeaderSize;
typedef struct {
	BYTE Header[iHeaderSize];
} PDFHeader;

local int iTrailerSize;
typedef struct {
	BYTE Trailer[iTrailerSize];
} PDFTrailer;

local int iUnknownSize;
typedef struct {
	BYTE Data[iUnknownSize];
} PDFUnknown;

local int iCommentSize;
typedef struct {
	BYTE Comment[iCommentSize];
} PDFComment;

local int iWhitespaceSize;
typedef struct {
	BYTE Whitespace[iWhitespaceSize] <fgcolor=cLtGray>;
} PDFWhitespace;

typedef struct (int idLen, int countLen, int crlfLen) {
    BYTE id[idLen];
    char ws1 <hidden=true>;
    CHAR count[countLen];
    byte crlf[crlfLen] <hidden=true>;
    struct {
        iWhitespaceSize = 1;
        BYTE offset[10];
        PDFWhitespace w <hidden=true>;
        BYTE generationNumber[5];
        PDFWhitespace w <hidden=true>;
        BYTE used;
        byte crlf[2] <hidden=true>;
    } PDFXrefItem[Atoi(count)];
} PDFXref;

// Functions

int64 FindStartOfObj(int64 iStart, int &iIndexLength, int &iWhiteSpace1Length, int &iVersionLength, int &iWhiteSpace2Length)
{
	local int iIter;
	local BYTE bChar;
	local int64 iIndex;
	local int64 iStartIndex = -1;
	local int64 iEndIndex = -1;
	local int64 iStartVersion = -1;
	local int64 iEndVersion = -1;

	for(iIter = 1; iIter <= 20; iIter++)
	{
		iIndex = iStart - iIter;
		if (iIndex < 0)
			break;
		bChar = ReadByte(iIndex);
		if (iEndVersion == -1)
		{
			if (bChar == ' ')
				;
			else if (bChar >= '0' && bChar <= '9')
				iEndVersion = iIndex;
			else
				break;
		}
		else if (iStartVersion == -1)
		{
			if (bChar >= '0' && bChar <= '9')
				;
			else if (bChar == ' ')
				iStartVersion = iIndex + 1;
			else
				break;
		}
		else if (iEndIndex == -1)
		{
			if (bChar == ' ')
				;
			else if (bChar >= '0' && bChar <= '9')
				iEndIndex = iIndex;
			else
				break;
		}
		else if (iStartIndex == -1)
		{
			if (bChar < '0' || bChar > '9')
			{
				iStartIndex = iIndex + 1;
				break;
			}
		}
	}

	if (iEndIndex != -1 && iStartVersion != -1 && iEndVersion != -1)
	{
		if (iStartIndex == -1)
		{
			if (iIndex == -1)
				iStartIndex = 0;
			else
				return -1;
		}
		iIndexLength = iEndIndex - iStartIndex + 1;
		iWhiteSpace1Length = iStartVersion - iEndIndex - 1;
		iVersionLength = iEndVersion - iStartVersion + 1;
		iWhiteSpace2Length = iStart - iEndVersion;
		return iStartIndex;
	}
	else
		return -1;
}

int64 FindEOL(int64 iStart)
{
	local int64 iIter;
	for(iIter = iStart; iIter < FileSize(); iIter++)
		if (ReadByte(iIter) == 0x0D && iIter + 1 < FileSize() && ReadByte(iIter + 1) == 0x0A)
			return iIter + 1;
		else if (ReadByte(iIter) == 0x0D || ReadByte(iIter) == 0x0A)
			return iIter;
	return -1;
}

void FindAllKeywords(void)
{
	tfrHeaders = FindAll("%PDF");
	tfrTrailers = FindAll("%%EOF");
	tfrObjs = FindAll(" obj");
	tfrEndobjs = FindAll("endobj");
	iKeywordCount = tfrHeaders.count + tfrTrailers.count + tfrObjs.count + tfrEndobjs.count;
}

int MergeKeywords(int iMerge1Size, int iMerge2Size)
{
	local int64 iIndex1 = 0;
	local int64 iIndex2 = 0;
	local int64 iIndex3 = 0;

	while (true)
	{
		if (iIndex1 == iMerge1Size)
		{
			while (iIndex2 < iMerge2Size)
			{
				aiMerge3KeywordType[iIndex3] = aiMerge2KeywordType[iIndex2];
				aiMerge3KeywordStart[iIndex3] = aiMerge2KeywordStart[iIndex2];
				aiMerge3KeywordSize[iIndex3] = aiMerge2KeywordSize[iIndex2];
				iIndex2++;
				iIndex3++;
			}
			break;
		}
		if (iIndex2 == iMerge2Size)
		{
			while (iIndex1 < iMerge1Size)
			{
				aiMerge3KeywordType[iIndex3] = aiMerge1KeywordType[iIndex1];
				aiMerge3KeywordStart[iIndex3] = aiMerge1KeywordStart[iIndex1];
				aiMerge3KeywordSize[iIndex3] = aiMerge1KeywordSize[iIndex1];
				iIndex1++;
				iIndex3++;
			}
			break;
		}
		if (aiMerge1KeywordStart[iIndex1] < aiMerge2KeywordStart[iIndex2])
		{
			aiMerge3KeywordType[iIndex3] = aiMerge1KeywordType[iIndex1];
			aiMerge3KeywordStart[iIndex3] = aiMerge1KeywordStart[iIndex1];
			aiMerge3KeywordSize[iIndex3] = aiMerge1KeywordSize[iIndex1];
			iIndex1++;
			iIndex3++;
		}
		else
		{
			aiMerge3KeywordType[iIndex3] = aiMerge2KeywordType[iIndex2];
			aiMerge3KeywordStart[iIndex3] = aiMerge2KeywordStart[iIndex2];
			aiMerge3KeywordSize[iIndex3] = aiMerge2KeywordSize[iIndex2];
			iIndex2++;
			iIndex3++;
		}
	}
	for(iIndex1 = 0; iIndex1 < iMerge1Size + iMerge2Size; iIndex1++)
	{
		aiMerge1KeywordType[iIndex1] = aiMerge3KeywordType[iIndex1];
		aiMerge1KeywordStart[iIndex1] = aiMerge3KeywordStart[iIndex1];
		aiMerge1KeywordSize[iIndex1] = aiMerge3KeywordSize[iIndex1];
	}
	return iMerge1Size + iMerge2Size;
}

void MergeAndFilterAllKeywords(void)
{
	local int iIter;
	local int iIter2;
	local int iTempCount;

	for(iIter = 0; iIter < tfrHeaders.count; iIter++)
	{
		aiMerge1KeywordType[iIter] = TYPE_HEADER;
		aiMerge1KeywordStart[iIter] = tfrHeaders.start[iIter];
		aiMerge1KeywordSize[iIter] = tfrHeaders.size[iIter];
	}
	for(iIter = 0; iIter < tfrTrailers.count; iIter++)
	{
		aiMerge2KeywordType[iIter] = TYPE_TRAILER;
		aiMerge2KeywordStart[iIter] = tfrTrailers.start[iIter];
		aiMerge2KeywordSize[iIter] = tfrTrailers.size[iIter];
	}
	iTempCount = MergeKeywords(tfrHeaders.count, tfrTrailers.count);
	iIter2 = 0;
	for(iIter = 0; iIter < tfrObjs.count; iIter++)
	{
		if (-1 != FindStartOfObj(tfrObjs.start[iIter], iIndexLength, iWhiteSpace1Length, iVersionLength, iWhiteSpace2Length))
		{
			aiMerge2KeywordType[iIter2] = TYPE_OBJ;
			aiMerge2KeywordStart[iIter2] = tfrObjs.start[iIter];
			aiMerge2KeywordSize[iIter2] = tfrObjs.size[iIter];
			iIter2++;
		}
	}
	iTempCount = MergeKeywords(iTempCount, iIter2);
	for(iIter = 0; iIter < tfrEndobjs.count; iIter++)
	{
		aiMerge2KeywordType[iIter] = TYPE_ENDOBJ;
		aiMerge2KeywordStart[iIter] = tfrEndobjs.start[iIter];
		aiMerge2KeywordSize[iIter] = tfrEndobjs.size[iIter];
	}
	iKeywordCount = MergeKeywords(iTempCount, tfrEndobjs.count);
}

int CalculateSizeWithEOL(int64 iStart)
{
	local int64 iIndexEOL;

	iIndexEOL = FindEOL(iStart);
	if (iIndexEOL == -1)
		return -1;
	else
		return iIndexEOL - iStart + 1;
}

void PrepareStructures(void)
{
	local int iIter;
	local int64 iEndPreviousStructure = 0;
	local int iSize;
	local int64 iStartIndirectObject;
	local BYTE bRead;
	local int iWhitespaceCount;
	iStructureCount = 0;

	for(iIter = 0; iIter < iKeywordCount; iIter++)
	{
		if (aiMerge1KeywordType[iIter] == TYPE_OBJ)
			iStartIndirectObject = FindStartOfObj(aiMerge1KeywordStart[iIter], iIndexLength, iWhiteSpace1Length, iVersionLength, iWhiteSpace2Length);
		else
			iStartIndirectObject = aiMerge1KeywordStart[iIter];

		if (iStartIndirectObject != iEndPreviousStructure && aiMerge1KeywordType[iIter] != TYPE_ENDOBJ)
		{
			aiStructureType[iStructureCount] = TYPE_UNKNOWN;
			aiStructureStart[iStructureCount] = iEndPreviousStructure;
			aiStructureSize[iStructureCount] = iStartIndirectObject - iEndPreviousStructure;
			iStructureCount++;
		}

		if (aiMerge1KeywordType[iIter] == TYPE_HEADER)
		{
			iSize = CalculateSizeWithEOL(aiMerge1KeywordStart[iIter]);
			if (iSize == -1)
				iSize = aiMerge1KeywordSize[iIter];
			aiStructureType[iStructureCount] = TYPE_HEADER;
			aiStructureStart[iStructureCount] = aiMerge1KeywordStart[iIter];
			aiStructureSize[iStructureCount] = iSize;
			iEndPreviousStructure = aiStructureStart[iStructureCount] + aiStructureSize[iStructureCount];
			iStructureCount++;
		}
		else if (aiMerge1KeywordType[iIter] == TYPE_TRAILER)
		{
			iSize = CalculateSizeWithEOL(aiMerge1KeywordStart[iIter]);
			if (iSize == -1)
				iSize = aiMerge1KeywordSize[iIter];
			aiStructureType[iStructureCount] = TYPE_TRAILER;
			aiStructureStart[iStructureCount] = aiMerge1KeywordStart[iIter];
			aiStructureSize[iStructureCount] = iSize;
			iEndPreviousStructure = aiStructureStart[iStructureCount] + aiStructureSize[iStructureCount];
			iStructureCount++;
		}
		else if (aiMerge1KeywordType[iIter] == TYPE_OBJ)
		{
			iSize = aiMerge1KeywordStart[iIter + 1] - iStartIndirectObject;
			if (aiMerge1KeywordType[iIter + 1] == TYPE_ENDOBJ)
				iSize += 6;
			iWhitespaceCount = 0;
			bRead = ReadByte(iStartIndirectObject + iSize);
			while (bRead == 0x0D || bRead == 0x0A || bRead == 0x20)
			{
				iWhitespaceCount++;
				bRead = ReadByte(iStartIndirectObject + iSize + iWhitespaceCount);
			}
			iSize += iWhitespaceCount;
			aiStructureType[iStructureCount] = TYPE_OBJ;
			aiStructureStart[iStructureCount] = iStartIndirectObject;
			aiStructureSize[iStructureCount] = iSize;
			aiStructureExtraParameter1[iStructureCount] = iIndexLength;
			aiStructureExtraParameter2[iStructureCount] = iWhiteSpace1Length;
			aiStructureExtraParameter3[iStructureCount] = iVersionLength;
			aiStructureExtraParameter4[iStructureCount] = iWhiteSpace2Length;
			aiStructureExtraParameter5[iStructureCount] = aiMerge1KeywordType[iIter + 1] == TYPE_ENDOBJ;
			aiStructureExtraParameter6[iStructureCount] = iWhitespaceCount;
			iEndPreviousStructure = aiStructureStart[iStructureCount] + aiStructureSize[iStructureCount];
			iStructureCount++;
		}
	}

	// code for unknown structure after last keyword
	if (FileSize() - aiStructureStart[iStructureCount - 1] - aiStructureSize[iStructureCount - 1] != 0)
	{
		aiStructureType[iStructureCount] = TYPE_UNKNOWN;
		aiStructureStart[iStructureCount] = aiStructureStart[iStructureCount - 1] + aiStructureSize[iStructureCount - 1];
		aiStructureSize[iStructureCount] = FileSize() - aiStructureStart[iStructureCount - 1] - aiStructureSize[iStructureCount - 1];
		iStructureCount++;
	}
}

void CreatePDFHeader(int64 iStart, int iSize)
{
	iPDFHeaderCount++;
	FSeek(iStart);
	iHeaderSize = iSize;
	PDFHeader sPDFHeader;
}

void CreatePDFTrailer(int64 iStart, int iSize)
{
	iPDFTrailerCount++;
	FSeek(iStart);
	iTrailerSize = iSize;
	PDFTrailer sPDFTrailer;
}

void CreatePDFUnknown(int64 iStart, int iSize)
{
	iPDFUnknownCount++;
	FSeek(iStart);
	iUnknownSize = iSize;
	PDFUnknown sPDFUnknown;
}

void CreatePDFComment(int64 iStart, int iSize)
{
	iPDFCommentCount++;
	FSeek(iStart);
	iCommentSize = iSize;
	PDFComment sPDFComment;
}

int IsWhitespace(int64 iStart, int iSize)
{
	local int64 iIter;
	local BYTE bRead;

	for(iIter = iStart; iIter < iStart + iSize; iIter++)
	{
		bRead = ReadByte(iIter);
		if (bRead != 0x09 && bRead != 0x0A && bRead != 0x0D && bRead != 0x20)
			return false;
	}
	return true;
}

void CreatePDFWhitespace(int64 iStart, int iSize)
{
	iPDFWhitespaceCount++;
	FSeek(iStart);
	iWhitespaceSize = iSize;
	PDFWhitespace sPDFWhitespace;
}

int StartsWith(int64 iStart, int iSize, string sData)
{
	local int64 iIter;

	if (Strlen(sData) > iSize)
		return false;

	for(iIter = 0; iIter < Strlen(sData); iIter++)
		if (ReadByte(iStart + iIter) != sData[iIter])
			return false;
	return true;
}

void CreatePDFXref(int64 iStart, int iSize)
{
	iPDFXrefCount++;
    local char xRefLine[] = ReadLine(iStart);
    local int64 nextStart = iStart + Strlen(xRefLine);
    FSeek(nextStart);
    local char l[] = ReadLine(nextStart, -1, 0);
    local int idLen = Strstr(l, " ");
    local int countLen = Strlen(l) - idLen - 1;
    local int crlfLen = (Strlen(ReadLine(nextStart, -1, 1)) - Strlen(l));
    PDFXref sPDFXref(idLen, countLen, crlfLen);
}

void CreatePDFObject(int64 iStart, int iSize, int iIndexLengthArg, int iWhiteSpace1LengthArg, int iVersionLengthArg, int iWhiteSpace2LengthArg, int iFoundEndobjArg, int iWhiteSpace3LengthArg)
{
	iPDFObjectCount++;
	iIndexLength = iIndexLengthArg;
	iWhiteSpace1Length = iWhiteSpace1LengthArg;
	iVersionLength = iVersionLengthArg;
	iWhiteSpace2Length = iWhiteSpace2LengthArg;
	iFoundEndobj = iFoundEndobjArg;
	iWhiteSpace3Length = iWhiteSpace3LengthArg;
	FSeek(iStart);
	iDataLength = iSize - iIndexLength - iWhiteSpace1Length - iVersionLength - iWhiteSpace2Length - 6 - 3 - iWhiteSpace3LengthArg;
	PDFObj sPDFObj;
}

local int iToggleColor = iCOLOR;
void ToggleBackColor()
{
	if (iToggleColor == iCOLOR)
		iToggleColor = cNone;
	else
		iToggleColor = iCOLOR;
	SetBackColor(iToggleColor);
}

void CreatePDFStructures(void)
{
	local int iIter;
	for(iIter = 0; iIter < iStructureCount; iIter++)
	{
		ToggleBackColor();
		if (aiStructureType[iIter] == TYPE_UNKNOWN && StartsWith(aiStructureStart[iIter], aiStructureSize[iIter], "%"))
			CreatePDFComment(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_UNKNOWN && StartsWith(aiStructureStart[iIter], aiStructureSize[iIter], "xref"))
			CreatePDFXref(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_UNKNOWN && IsWhitespace(aiStructureStart[iIter], aiStructureSize[iIter]))
			CreatePDFWhitespace(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_UNKNOWN)
			CreatePDFUnknown(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_HEADER)
			CreatePDFHeader(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_TRAILER)
			CreatePDFTrailer(aiStructureStart[iIter], aiStructureSize[iIter]);
		else if (aiStructureType[iIter] == TYPE_OBJ)
			CreatePDFObject(aiStructureStart[iIter], aiStructureSize[iIter], aiStructureExtraParameter1[iIter], aiStructureExtraParameter2[iIter], aiStructureExtraParameter3[iIter], aiStructureExtraParameter4[iIter], aiStructureExtraParameter5[iIter], aiStructureExtraParameter6[iIter]);
	}
	SetBackColor(cNone);
}

void PrintPDFCounters(void)
{
	Printf("Structure counts:\n");
	Printf("  PDFHeader     = %5d\n", iPDFHeaderCount);
	Printf("  PDFTrailer    = %5d\n", iPDFTrailerCount);
	Printf("  PDFObject     = %5d\n", iPDFObjectCount);
	Printf("  PDFComment    = %5d\n", iPDFCommentCount);
	Printf("  PDFXref       = %5d\n", iPDFXrefCount);
	Printf("  PDFWhitespace = %5d\n", iPDFWhitespaceCount);
	Printf("  PDFUnknown    = %5d\n", iPDFUnknownCount);
}

// Main

FindAllKeywords();
if (iKeywordCount == 0)
{
	Printf("Keywords not found, not a PDF file!\n");
	return;
}

local int aiMerge1KeywordType[iKeywordCount];
local int64 aiMerge1KeywordStart[iKeywordCount];
local int aiMerge1KeywordSize[iKeywordCount];
local int aiMerge2KeywordType[iKeywordCount];
local int64 aiMerge2KeywordStart[iKeywordCount];
local int aiMerge2KeywordSize[iKeywordCount];
local int aiMerge3KeywordType[iKeywordCount];
local int64 aiMerge3KeywordStart[iKeywordCount];
local int aiMerge3KeywordSize[iKeywordCount];

MergeAndFilterAllKeywords();

local int aiStructureType[iKeywordCount * 2 + 1];
local int64 aiStructureStart[iKeywordCount * 2 + 1];
local int aiStructureSize[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter1[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter2[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter3[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter4[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter5[iKeywordCount * 2 + 1];
local int aiStructureExtraParameter6[iKeywordCount * 2 + 1];

PrepareStructures();

CreatePDFStructures();

PrintPDFCounters();

转载请注明:夜羽的博客 » 【原创】通过PDF攻击溯源

喜欢 (0)or分享 (0)
隐藏
变装