反向工程在Windows上收听此设备-在没有API的情况下对Windows进行反向工程

px9o7tmv  于 7个月前  发布在  Windows
关注(0)|答案(1)|浏览(94)

我正在使用autohotkey编写一个脚本来切换麦克风的“收听此设备”:


的数据
有两个步骤来实现这一点,首先我需要找出什么注册表项正在修改,我能够完成这一使用RegShot。
密钥存在于:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture\{My-Microphone's-UUID}\Properties

字符串
这个键叫做{24dbb0fc-9311-4b3d-9cf0-18ff155639d4},1(不只是我的笔记本电脑,而是所有的电脑)。
切换“Listen to this device”时的值会像这样变化:(0的值变为f)

xxxxxxxxxxxxxxxx0000xxxx
xxxxxxxxxxxxxxxxffffxxxx


第二步是我的问题所在,当我检查GUI时,我看到“Listen to this device”tickbox已经被勾选,但我实际上听不到麦克风的任何声音,当我取消勾选它然后点击应用并重新勾选它并点击应用时,我听到我的麦克风。这意味着我需要某种DllCall或PostMessage,但这是我非常欠缺的地方:
我不知道如何使windows了解此设置已更改,我需要找出什么消息被发送或什么动态链接库被称为当我点击“应用”。
所以我在谷歌上搜索了List of Windows Messages,我真的发布了页面上存在的每一个hex,就像这样:

PostMessage, 0x0000,,,,A
...
PostMessage, 0xcccd,,,,A


当然,这并不起作用,这是在黑暗中拍摄。
在Sound GUI和from this article上使用Autohotkey的WindowSpy,我发现shell32.dll可能涉及到这一点,所以使用nirsoft的DLL导出查看器,我复制了shell32中存在的所有函数,并使用Autohotkey调用所有函数,如下所示:

DllCall("shell32\Control_RunDLL")
...


但这也不管用。
起初我想,这是一个编程问题,它可以用Autohotkey和它的工具来回答,所以我在SO上问了这个问题,但我已经要求将它移到RE上,因为下面的评论给了我更多的见解。
请教我如何正确地进行逆向工程。

fnx2tebb

fnx2tebb1#

感谢RE上的this answer,我能够提出一个适当的代码示例来设置是否启用/禁用监听,以及应该在哪个设备上监听-包括“默认播放设备”设置。
这是在python中使用pycaw和comtypes,但我认为它可以很容易地用其他具有coreaudio库的语言来完成。

from typing import Optional
from comtypes import GUID
from comtypes.automation import VT_BOOL, VT_LPWSTR, VT_EMPTY
from comtypes.persist import STGM_READWRITE
from pycaw.api.mmdeviceapi import PROPERTYKEY

from pycaw.api.mmdeviceapi.depend import PROPVARIANT
from pycaw.utils import AudioUtilities

#Hardcoded values
LISTEN_SETTING_GUID = "{24DBB0FC-9311-4B3D-9CF0-18FF155639D4}"
CHECKBOX_PID = 1
LISTENING_DEVICE_PID = 0

#Values you can change:
microphone_name = 'Microphone (USB-MIC)'
listening_device_name = 'Speakers (5- GSA 70 Main Audio)'   #Set to 'None' to use the default playback device
enable_listening = False

def main():
    store = get_device_store(microphone_name)
    if store is None:
        print("failed to open property store")
        exit(1)

    set_listening_checkbox(store, enable_listening)
    set_listening_device(store, listening_device_name)

#Write to the checkbox property
def set_listening_checkbox(property_store, value:bool):
    checkbox_pk = PROPERTYKEY()
    checkbox_pk.fmtid = GUID(LISTEN_SETTING_GUID)
    checkbox_pk.pid = CHECKBOX_PID

    new_value = PROPVARIANT(VT_BOOL)
    new_value.union.boolVal = value
    property_store.SetValue(checkbox_pk, new_value)

#Write to the device property
def set_listening_device(property_store, output_device_name:Optional[str]):
    if output_device_name is not None:
        listening_device_guid = get_GUID_from_name(output_device_name)
    else:
        listening_device_guid = None

    device_pk = PROPERTYKEY()
    device_pk.fmtid = GUID(LISTEN_SETTING_GUID)
    device_pk.pid = LISTENING_DEVICE_PID

    if listening_device_guid is not None:
        new_value = PROPVARIANT(VT_LPWSTR)
        new_value.union.pwszVal = listening_device_guid
    else:
        new_value = PROPVARIANT(VT_EMPTY)

    property_store.SetValue(device_pk, new_value)

#Gets the device store from the device name
def get_device_store(device_name:str):
    device_guid = get_GUID_from_name(device_name)
    enumerator = AudioUtilities.GetDeviceEnumerator()
    dev = enumerator.GetDevice(device_guid)

    store = dev.OpenPropertyStore(STGM_READWRITE)
    return store

#This is just a helper method to turn a device name into a GUID.
def get_GUID_from_name(device_name:str) -> str:
    input_devices = get_list_of_active_coreaudio_devices("input")
    for device in input_devices:
        if device.FriendlyName == device_name:
            return device.id
    output_devices = get_list_of_active_coreaudio_devices("output")
    for device in output_devices:
        if device.FriendlyName == device_name:
            return device.id
    raise ValueError("Device not found!")

#Helper method to get all (active) devices
def get_list_of_active_coreaudio_devices(device_type:str) -> list:
    import comtypes
    from pycaw.pycaw import AudioUtilities, IMMDeviceEnumerator, EDataFlow, DEVICE_STATE
    from pycaw.constants import CLSID_MMDeviceEnumerator

    if device_type != "output" and device_type != "input":
        raise ValueError("Invalid audio device type.")

    if device_type == "output":
        EDataFlowValue = EDataFlow.eRender.value
    else:
        EDataFlowValue = EDataFlow.eCapture.value
    # Code to enumerate devices adapted from https://github.com/AndreMiras/pycaw/issues/50#issuecomment-981069603

    devices = list()
    device_enumerator = comtypes.CoCreateInstance(
        CLSID_MMDeviceEnumerator,
        IMMDeviceEnumerator,
        comtypes.CLSCTX_INPROC_SERVER)
    if device_enumerator is None:
        raise ValueError("Couldn't find any devices.")
    collection = device_enumerator.EnumAudioEndpoints(EDataFlowValue, DEVICE_STATE.ACTIVE.value)
    if collection is None:
        raise ValueError("Couldn't find any devices.")

    count = collection.GetCount()
    for i in range(count):
        dev = collection.Item(i)
        if dev is not None:
            if not ": None" in str(AudioUtilities.CreateDevice(dev)):
                devices.append(AudioUtilities.CreateDevice(dev))

    return devices

if __name__ == "__main__":
    main()

字符串

相关问题