[原创]Pdf密码破解算法逆向
软件名称 PasswareKitBasic.exe
软件版本 Passware Kit 12 Demo 和 Passware Kit 11 Demo
下载地址 www.lostpassword.com
把pdf破解算法的逆向记录分享一下,有理解错误的地方还请大家指正
Pdf密码有两种user password、owner password
这里的算法是破解user password。owner password可以直接移除不用破解
该版本不能破解acrobat10.0(acrobat X)
该版本主要包含三个破解算法RC4-40 RC4-128 AES-128
用acrobat工具生成各种加密版本来做测试
让程序跑起来,在线程窗口可以有三个线程在破解,选择在CPU中打开可以断在算法里(一次断不到算法里可以多试几次)
PDF加密后的文件尾部(trailer)
trailer
<</Size 28/Encrypt 29 0 R>>
startxref
116
%%EOF
29 0 obj <</Length128
/Filter/Standard
/O(154747F335FB401F338AAA1310E11E63D6B9F7D0FCA78DD48ED834C9CB7AC976)
/P-1028
/R3
/U(02093CD04060F432EA87F6985AFFDD78676E5F66000000005900A00130C53F00)
/V 2>> endobj
从Adobe? Portable Document Format文档里可以找到:
/Length 密钥的长度
/Filter 生成密钥的方法,就是前面说的security handler
/O 是由用户口令和权限口令得到的,用来生成密钥和验证输入的权限口令
/P 访问权限的标志
/R 标准加密的(standard security handler)的版本
/U由用户口令生成,用来验证输入的用户口令或权限口令,是否要提醒用户输入密码
/V 可选,用来指明加密的算法。
/P访问权限标识详细
1-2 保留为0;
3 (版本2) 打印文档
(版本3或者更高)打印文档(可能不是最高级别,取决于bit 12是否被设置)
4 Modify the contents of the document by operations other than those controlled by bits 6, 9, and 11.
通过控制bit 6、bit 9、bit11修改文档内容
5 (版本2)Copy or otherwise extract text and graphics from the document, including extracting text and graphics (in support of accessibility
to users with disabilities or for other purposes).
复制或提取文本和图形从文档,包括提取文本和图形(以支持可访问性受限用户或其他用途)。
(版本3或者更高) Copy or otherwise extract text and graphics from the document by operations other than that controlled by bit10.
通过控制bit 10 复制或提取文本和图形
6 Add or modify text annotations, fill in interactive form fields, and, if bit 4 is also set, create or modify interactive form fields (including signature fields).
添加或修改文本注释,填写交互式表单字段;如果bit 4被设置,创建或修改交互式表单字段(包括签名字段).
7-8 保留 为1;
9 (版本3或者更高) Fill in existing interactive form fields (including
signature fields), even if bit 6 is clear.
填充现有的交互表单字段(包括签名字段),即使 bit 6未设置.
10 (版本3或者更高) Extract text and graphics (in support of accessibility
to users with disabilities or for other purposes).
提取文本和图形(用来支持受限用户的可访问性或其他用途)
11 (版本3或者更高) Assemble the document (insert, rotate, or delete
pages and create bookmarks or thumbnail images), even if bit 4 is clear.
组合文档(插入、旋转或删除页面和创建书签或缩略图)即使bit 4未设置
12 (版本3或者更高) Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this bit is clear (and bit 3 is set), printing is limited to a low-level representation of the appearance, possibly of degraded quality. (See implementation note 25 in Appendix H.)
打印标识。当该位未设置并且bit 3被设置,打印受限。
13-32 (版本3或更高)保留 必须为1;
RC4-128算法
Algorithm part1 Computing an encryption key
1.密码字符串为N字节长度,用以下字符串
<28 BF 4E 5E 4E 75 8A 41 64 00 4E 56 FF FA 01 08 2E 2E 00 B6 D0 68 3E 80 2F 0C A9 FE 64 53 69 7A >
中的32-N个填充至32个字节。如果用户密码为空就全部填充.
2.初始化MD5,并将步骤1的结果输入到MD5函数.
3.通过加密字典中的O进入MD5哈希函数.
4.将P条目作为一个4字节无符号整数的值传递给MD5函数.
5.将文档ID的第一个元素传递给MD5.
6.如果文档metadata没有被加密传递0xFFFFFFFF到MD5函数.
7.结束MD5.
8.连续做50次:从上一个MD5函数的输出的n bytes传递到给MD5函数。其中n由加密字典条目的 length决定(length/8).
9.从最终的MD5输出的前n bytes设置为RC4加密密钥。对于版本2来说,n始终为5,但对于版本3或更高版本来说,取决于加密字典中
length的值(length/8).
Algorithm part2 Computing the encryption dictionary’s U (user password) value (Revision 3 or greater)
1.按照Algorithm part1的方法,基于用户口令字符串生成全局加密密钥.
2.初始化MD5函数并将按照Algorithm part1步骤1生产的32位字符串输入该函数.
3.将文件ID数组中的第一个32位ID字符串传入MD5函数.
4.用第1步产生的密钥通过RC4算法来加密由步骤3输出的16位字符串.
0B272D84 49DD8B1A
0B272D88 B546154D
0B272D8C 059A4C1A
0B272D90 AB3D50CE
22 30 da 73 56 e1 48 74 e9 7f 75 49 db 8a a4 a7
5.做19次运算:用前一次的输出作为下一次的输入进行解码;密钥是由第1步产生的原始密钥的单个字节和循环数xor运算得到的.
0AFFD3B4 C7A7C82B +颧
0AFFD3B8 1ED35085 匬?
0AFFD3BC 2F1EF1F4 赳_/
0AFFD3C0 28C6F209 .蚱(
3a fe 1a 3c 8b 61 45 b6 01 96 1b 06 c7 11 89 59
Passware Kit 11 Demo分析
填充后的数据
0AFFE084 BF289038
0AFFE088 754E5E4E
0AFFE08C 0064418A Passware.0064418A
0AFFE090 FAFF564E
0AFFE094 2E2E0801
0AFFE098 68D0B600
0AFFE09C 0C2F803E
0AFFE0A0 5364FEA9
0AFFE0A4 2494D79E
0AFFE0A8 888F3421
0AFFE0AC 67719CB7
0AFFE0B0 9E49855C
0AFFE0B4 4B36B2F9
0AFFE0B8 9246127F
0AFFE0BC CDAE7226
0AFFE0C0 5A206F65
0B017674 FFFFFBFC
0B017678 4E09775B
0B01767C 4CE72BD3
0B017680 4A9C5DA9
0B017684 E0B289D5
0B017688 00000080
0B01768C 00000000
0B017690 00000000
0B017694 00000000
0B017698 00000000
0B01769C 00000000
0B0176A0 00000000
0B0176A4 00000000
0B0176A8 00000000
0B0176AC 000002A0
0B0176B0 00000000
00A88CD6 |. E8 253A0000 |call Passware.00A8C700 ; TTT3
00A8C73C |. E8 06600000 call Passware.00A92747 ; TTT2
00C62470 /$ 55 push ebp ;算法 得到加密后的16 bits
00C62471 |. 8BEC mov ebp,esp
00C62473 |. 83EC 40 sub esp,0x40
00C62476 |. 53 push ebx
00C62477 |. 8B45 08 mov eax,[arg.1]
00C6247A |. 8B48 0C mov ecx,dword ptr ds:[eax+0xC]
00C6247D |. 8B10 mov edx,dword ptr ds:[eax]
00C6247F |. 56 push esi
00C62480 |. 8B70 04 mov esi,dword ptr ds:[eax+0x4]
00C62483 |. 57 push edi
00C62484 |. 8B78 08 mov edi,dword ptr ds:[eax+0x8]
00C62487 |. 8B45 0C mov eax,[arg.2]
00A8D1EA |> \8B08 mov ecx,dword ptr ds:[eax]
00A8D1EC |. 310F xor dword ptr ds:[edi],ecx
00A8D1EE |. 8B50 04 mov edx,dword ptr ds:[eax+0x4]
00A8D1F1 |. 3157 04 xor dword ptr ds:[edi+0x4],edx
00A8D1F4 |. 8B48 08 mov ecx,dword ptr ds:[eax+0x8]
00A8D1F7 |. 314F 08 xor dword ptr ds:[edi+0x8],ecx
00A8D1FA |. 8B50 0C mov edx,dword ptr ds:[eax+0xC]
00A8D1FD |. 3157 0C xor dword ptr ds:[edi+0xC],edx
00A8E100 /$ 89F8 mov eax,edi ;MD5算法
00A8E102 |. 8B0A mov ecx,dword ptr ds:[edx]
00A8E104 |. 31F0 xor eax,esi
00A8E106 |. 81C1 78A46AD7 add ecx,0xD76AA478
00A8E10C |. 21D8 and eax,ebx
00A8E10E |. 01CD add ebp,ecx
00A8E110 |. 31F8 xor eax,edi
00A8E112 |. 8B4A 04 mov ecx,dword ptr ds:[edx+0x4]
00A8E115 |. 01C5 add ebp,eax
00A8E117 |. 81C1 56B7C7E8 add ecx,0xE8C7B756
00A8E11D |. C1C5 07 rol ebp,0x7
00A8E120 |. 01CF add edi,ecx
00A8E122 |. 89F0 mov eax,esi
00A8E124 |. 01DD add ebp,ebx
00A8E126 |. 31D8 xor eax,ebx
00A8E128 |. 8B4A 08 mov ecx,dword ptr ds:[edx+0x8]
00A8E12B |. 21E8 and eax,ebp
00A8E12D |. 81C1 DB702024 add ecx,0x242070DB
00A8E133 |. 31F0 xor eax,esi
逆出来的算法代码(伪代码)
int JudgePdfPasswordRC4_128()
{
int j=0;
int rc4_count=0;
UINT4 _State[4];
UCHAR S[256];
UINT state[4];
UCHAR local_converStateEnd[16];
memcpy(local_converStateEnd,converStateEnd,16);
j=strlen(pdf_szZu);
memcpy(CheckArea1,pdf_szZu,j);
memcpy(CheckArea1+j,ConData,32-j);
memcpy(_State,g_State,16);//取代reset();
md5_transform_assembly(_State,CheckArea1);
md5_transform_assembly(_State,CheckArea1 + 0x40);
for(int md5_count = 0;md5_count != 50;++md5_count)//50次MD5算法
{
memcpy(CheckArea2,_State,16);
memcpy(_State,g_State,16);//取代reset();
CMD5::MD5Transform(_State,CheckArea2);
}
RC4_assemly(S, (const UCHAR*)_State, local_converStateEnd);
for (rc4_count=0;rc4_count!=18;rc4_count++)//18次RC4算法
{
state[0]=_State[0]^cnt_X[rc4_count];
state[1]=_State[1]^cnt_X[rc4_count];
state[2]=_State[2]^cnt_X[rc4_count];
state[3]=_State[3]^cnt_X[rc4_count];
RC4_assemly(S, (const UCHAR*)state, local_converStateEnd);
}
state[0]=_State[0]^cnt_X[rc4_count];
state[1]=_State[1]^cnt_X[rc4_count];
state[2]=_State[2]^cnt_X[rc4_count];
state[3]=_State[3]^cnt_X[rc4_count];
return RC4AndResult(S,m_lin,local_converStateEnd,sizeof(local_converStateEnd),(char*)state,16);
//第19次RC4算法并作判断
}
RC4-40算法分析
Passware Kit 11 Demo分析
数据处理部分
00A8D07D |. 310F xor dword ptr ds:[edi],ecx
00A8D07F |. 8B50 04 mov edx,dword ptr ds:[eax+0x4]
00A8D082 |. 3157 04 xor dword ptr ds:[edi+0x4],edx
00A8D085 |. 8B48 08 mov ecx,dword ptr ds:[eax+0x8]
00A8D088 |. 314F 08 xor dword ptr ds:[edi+0x8],ecx
00A8D08B |. 8B50 0C mov edx,dword ptr ds:[eax+0xC]
00A8D08E |. 3157 0C xor dword ptr ds:[edi+0xC],edx
00A8D091 |. 8B48 10 mov ecx,dword ptr ds:[eax+0x10]
00A8D094 |. 314F 10 xor dword ptr ds:[edi+0x10],ecx
00A8D097 |. 8B50 14 mov edx,dword ptr ds:[eax+0x14]
00A8D09A |. 3157 14 xor dword ptr ds:[edi+0x14],edx
00A8D09D |. 8B48 18 mov ecx,dword ptr ds:[eax+0x18]
00A8D0A0 |. 314F 18 xor dword ptr ds:[edi+0x18],ecx
00A8D0A3 |. 8B50 1C mov edx,dword ptr ds:[eax+0x1C]
00A8D0A6 |. 3157 1C xor dword ptr ds:[edi+0x1C],edx
00A8D0A9 |. 8B4E 3C mov ecx,dword ptr ds:[esi+0x3C]
00A91503 |. E8 F8CBFFFF call Passware.00A8E100 ; MD5算法
32字节填充数据
5E4EBF28
418A754E
564E0064 与U条目异或
0801FAFF ----------------->生成最终数据
B6002E2E
803E68D0
FEA90C2F
7A695364
0AFFE084 BF289038
0AFFE088 754E5E4E
0AFFE08C 0064418A Passware.0064418A
0AFFE090 FAFF564E
0AFFE094 2E2E0801
0AFFE098 68D0B600
0AFFE09C 0C2F803E
0AFFE0A0 5364FEA9
0AFFE0A4 2494D79E
0AFFE0A8 888F3421
0AFFE0AC 67719CB7
0AFFE0B0 9E49855C
0AFFE0B4 4B36B2F9
0AFFE0B8 9246127F
0AFFE0BC CDAE7226
0AFFE0C0 5A206F65 经过两次MD5处理,再经过RC4处理后与最终数据比较
0B017674 FFFFFBFC --------------------------------------------------> 判别结果
0B017678 4E09775B
0B01767C 4CE72BD3
0B017680 4A9C5DA9
0B017684 E0B289D5
0B017688 00000080
0B01768C 00000000
0B017690 00000000
0B017694 00000000
0B017698 00000000
0B01769C 00000000
0B0176A0 00000000
0B0176A4 00000000
0B0176A8 00000000
0B0176AC 000002A0
0B0176B0 00000000
逆向的代码(伪代码)
int JudgePassword_RC4_40()
{
j=strlen(pdf_szZu);//pdf_szZu为传入的密码字符串
memcpy(CheckArea1,pdf_szZu,j);
memcpy(CheckArea1 + j,ConData,32-j);
memcpy(_State,g_State,16);//取代reset();
CMD5::MD5Transform(_State,CheckArea1);
CMD5::MD5Transform(_State,CheckArea1 + 0x40);
return RC4_40_AndResult(S,m_lin,converState_RC4_40,32,(char*)_State,5);
}
AES-128算法分析
Passware Kit 12 Demo分析
00B1D8C0 /$ 55 push ebp //Passware Kit 12 Demo 算法入口
00B2537B |. 8B45 08 mov eax,[arg.1]
00B2537E |. 8B5D 0C mov ebx,[arg.2]
00B25381 |. 8BF1 mov esi,ecx
00B25383 |. 8B4E 04 mov ecx,dword ptr ds:[esi+0x4]
00B25386 |. 8B56 08 mov edx,dword ptr ds:[esi+0x8]
00B25389 |. 8945 A4 mov [local.23],eax
00B2538C |. 8D040B lea eax,dword ptr ds:[ebx+ecx]
00B2538F |. 894D A0 mov [local.24],ecx
00B25392 |. 8946 04 mov dword ptr ds:[esi+0x4],eax //写入1字节数据(长度)
00B24E55 |. 8B46 04 mov eax,dword ptr ds:[esi+0x4]
00B24E58 |. 03C0 add eax,eax
00B24E5A |. 03C0 add eax,eax
00B24E5C |. 03C0 add eax,eax
00B24E5E |. 85FF test edi,edi
00B24E60 |. 74 02 je short Passware.00B24E64
00B24E62 |. 0FC8 bswap eax
00B24E64 |> 8BC8 mov ecx,eax
00B24E66 |. 8B45 F8 mov eax,[local.2]
00B24E69 |. C1E8 02 shr eax,0x2
00B24E6C |. 8D1438 lea edx,dword ptr ds:[eax+edi]
00B24E6F |. 894C93 F8 mov dword ptr ds:[ebx+edx*4-0x8],ecx //填充至最后
填充口令后的数据
0A511350 BF4BF020 餕
0A511354 E748B436 6碒
0A511358 000080BD 絸.. 填充方式:password + U条目最后8个字节 + 80+0 + 长度处理后的数据
0A51135C 00000000 ....
0A511360 00000000 ....
0A511364 00000000 ....
0A511368 00000000 ....
0A51136C 00000000 ....
0A511370 00000000 ....
0A511374 00000000 ....
0A511378 00000000 ....
0A51137C 00000000 ....
0A511380 00000000 ....
0A511384 00000000 ....
0A511388 00000000 ....
0A51138C 48000000 ...H
SHA256初始化(是SHA256?)
0A519D50 6A09E667 g?j
0A519D54 BB67AE85 叜g
0A519D58 3C6EF372 r髇<
0A519D5C A54FF53A :鮋
0A519D60 510E527F R_Q
0A519D64 9B05688C 宧_
0A519D68 1F83D9AB ?
0A519D6C 5BE0CD19 _袜[
循环处理
00977907 |. E8 84160000 |call Passware.00978F90 //传入字符
00978FF2 |. FFD0 call eax ; 填充字符1
00B2541F |. E8 FCD5F2FF call Passware.00A52A20 ; 填充字符2
0097901B |. FFD0 call eax ; 8888888888888888
00634D7B |. FFD2 call edx ;GOGO1
005F4A68 |. FFD2 call edx ; GOGO2
00B24EA1 |. FFD0 call eax ; 算法处理1
00B21344 |. E8 77C5FFFF call Passware.00B1D8C0 ; 算法
00B24EB5 |. E8 A6FDFFFF call Passware.00B24C60 ; GOGO3 bswap
00B24EC4 |. FFD0 call eax ; 数据初始化1
00633857 . E8 44A04E00 call Passware.00B1D8A0 ; 数据初始化
判断比较
SHA256算法处理后的数据与U条目前32个字节比较 PDF文件的U条目
0A51E369 9CBD1FAA ?綔 0A507210 967D44DD 軩}
0A51E36D CFA79CB3 硿 0A507214 06E32AD0 ??
0A51E371 DB0322CB ?_ 比较 0A507218 011727E8 ?__ Passware.011727E8
0A51E375 52081684 ?R -------------> 0A50721C 67D6B896 柛謌
0A51E379 2C4D47AF 疓M, 0A507220 8FE78FAC 瑥鐝
0A51E37D 2AC42E5D ].? 0A507224 FDA33377 w3}
0A51E381 F53D76BF 縱= 0A507228 46F680B4 磤鯢
0A51E385 5C809513 _晙\ 0A50722C DC388ADF 邐8
逆向的代码()
int JudgePdfPasswordAES128()
{
UCHAR UserPadd[64] = {0};
UCHAR* pUserPadd = UserPadd;
int sLen=strlen(pdf_szZu);
::memcpy(pUserPadd,pdf_szZu,sLen);
::memcpy(&UserPadd[sLen],pAppData_U + 32,8);
sLen = sLen + 8;
UserPadd[sLen] = 0x80;
__asm
{
mov eax,sLen
add eax,eax
add eax,eax
add eax,eax
mov esi,pUserPadd
add esi,0x3C
bswap eax
mov dword ptr [esi],eax
}
UINT* pSha256_r = NULL;
pSha256_r=Sha256_r;
UINT* pSha256_k = NULL;
pSha256_k = Sha256_k;
UINT importantData[8];
UINT* pimportantData = importantData;
__asm
{
pushad
sub esp,0x64
mov esi,pimportantData
mov dword ptr ss:[esp],esi
mov esi,pSha256_r
mov ecx,0x8
mov edi,esp
add edi,0x4
rep movsd
mov esi,pSha256_k
add esi,0xC0
mov dword ptr ss:[esp+0x64],esi
sub esi,0xC0
mov edx,pUserPadd
mov ebx,dword ptr [edx]
bswap ebx
mov dword ptr ss:[esp+0x60],ebx
mov ebx,dword ptr ds:[edx+0x4]
//内联汇编 省略……
label_1:
add esi,0x40
mov edx,dword ptr ss:[esp+0x18]
xor edx,dword ptr ss:[esp+0x1C]
and edx,edi
xor edx,dword ptr ss:[esp+0x1C]
//内联汇编 省略……
add edi,dword ptr ss:[esp+0x14]
mov dword ptr ss:[esp+0x14],edi
ror ebp,0x16
xor ebp,ebx
ror ebx,0xB
xor ebp,ebx
add ecx,ebp
mov dword ptr ss:[esp+0x4],ecx
cmp esi,dword ptr ss:[esp+0x64]
jb label_1
lea esi,[esp+0x4]
mov ecx,0x8
mov edi,[esp]
rep movsd
add esp,0x64
popad
}
for (int i=0;i != 8;++i)
{
importantData[i] += *(pSha256_r + i);
}
__asm
{
xor eax,eax
mov ebx,pimportantData
label_2:
mov edx,dword ptr [ebx+eax]
bswap edx
mov dword ptr [ebx+eax],edx
add eax,4
cmp eax,0x20
jb label_2
}
UINT *pUintAppData_U = (UINT*)pAppData_U;
for (int i = 0; i != 8;++i)
{
if(*(pUintAppData_U + i) != *(pimportantData + i))
return 1;
}
return 0;
}
