前言
每当我发现没有联网时总会点击右下角的Wifi标识进行联网,猛然间一大堆Wifi链接标识破门而入,这时候我感到十分奇怪,电脑是如何发现那些Wifi的呢?
引入
这时候我们又不得不扯到老朋友Wlanapi来帮忙了(Wlan之谜(一))。
函数1:WlanScan(Line 1258)
DWORD WINAPI
WlanScan(
_In_ HANDLE hClientHandle,
_In_ CONST GUID *pInterfaceGuid,
_In_opt_ CONST PDOT11_SSID pDot11Ssid,
_In_opt_ CONST PWLAN_RAW_DATA pIeData,
_Reserved_ PVOID pReserved
);
此函数将请求扫描指示的接口上的可用网络。
hClientHandle:记住,WindowsAPI 有三个经典到不能再经典的操作流程:
OpenHandle ----->Read/Write(print/scan)----->CloseHandle
= 打开门 走出去/走进来 关上门
不打开门就无法走出去/走进来(有人想“撞门”,结果撞出一个Assert警告框)
但是不关门那就有一点惨了……谁会溜进来呢?在门前占的空间怎么释放呢?
类似的还有fstream ,fopen , pcap(但我始终没找到)等。
所以hClientHandle是由函数WlanOpenHandle创造的。
GUID:唯一不重复标识符,等等,再聊一个函数,后面的参数可以用NULL或nullptr填充
函数1:WlanEnumInterfaces(Line 1191)
DWORD WINAPI
WlanEnumInterfaces(
_In_ HANDLE hClientHandle,
_Reserved_ PVOID pReserved,
_Outptr_ PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
);
hClientHandle:老套路,你开了门摸到了门把手(句柄),那么你到底走那一道门出去?换一个还是用当前这个?或者把他扔了?全球起码一百亿道门,打开的是那道?
pReserved:这个参数必须是NULL,一般Windows函数都有一个保留指针;
PWLAN_INTERFACE_INFO_LIST:呵呵,可以挖掘资源了,但千万不要把他当双指针(无限性列表)用,就把他取地址就好了。
于是,探测阶段就写好了!
DWORD dwResult = 0;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;
WCHAR GuidString[32] = { 0 };
HANDLE _wlanHandle = NULL;
PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
PWLAN_AVAILABLE_NETWORK pBssEntry = NULL;
DWORD dwCurVersion = 0;
DWORD dwMaxClient = 2;
if (_wlanHandle == NULL)
{
if ((dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &_wlanHandle)) != ERROR_SUCCESS)
{
std::cout << "wlanOpenHandle failed with error: " << dwResult << std::endl;
_wlanHandle = NULL;
return false;
}
}
// 释放内存
if (pBssList != NULL)
{
WlanFreeMemory(pBssList);
pBssList = NULL;
}
if (pIfList != NULL)
{
WlanFreeMemory(pIfList);
pIfList = NULL;
}
unsigned int i, j;
dwResult = WlanEnumInterfaces(_wlanHandle, NULL, &pIfList);
if (dwResult != ERROR_SUCCESS)
{
return false;
}
else
{
for (i = 0; i < (int)pIfList->dwNumberOfItems; i++)
{
pIfInfo = (WLAN_INTERFACE_INFO*)&pIfList->InterfaceInfo[i];
dwResult = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR)&GuidString,
sizeof(GuidString) / sizeof(*GuidString));
// 向无线网卡发送探测请求
dwResult = WlanScan(_wlanHandle, (const GUID*)(&pIfInfo->InterfaceGuid), NULL, NULL, NULL);
if (dwResult != ERROR_SUCCESS)
{
return false;
}
}
}
WlanCloseHandle(_wlanHandle);
函数3:WlanGetAvailableNetworkList(Line : 1267)
DWORD WINAPI
WlanGetAvailableNetworkList(
_In_ HANDLE hClientHandle,
_In_ CONST GUID *pInterfaceGuid,
_In_ DWORD dwFlags,
_Reserved_ PVOID pReserved,
_Outptr_ PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList
);
呵呵,大丰收来了!
wprintf(L"网卡名称: %s\n\n", pIfList->InterfaceInfo[i].strInterfaceDescription);
if (dwResult != ERROR_SUCCESS)
{
std::cout << "WlanGetAvailableNetworkList failed with error:" << dwResult;
return false;
}
for (j = 0; j < pBssList->dwNumberOfItems; j++)
{
pBssEntry = (WLAN_AVAILABLE_NETWORK*)&pBssList->Network[j];
std::string temp = std::string(reinterpret_cast<char*>(
pBssEntry->dot11Ssid.ucSSID));
if (temp.find("BugM") != std::string::npos)
{
std::cout << "===========ErrorGet==========" << std::endl;
}
wifilist.emplace_back(temp);
std::cout << (j+1) << ".Wifi Name:" << temp << std::endl;
PWLAN_BSS_LIST ppWlanBssList; //BSS网络列表
auto dwResult = WlanGetNetworkBssList(
_wlanHandle,
&pIfList->InterfaceInfo[i].InterfaceGuid,
&pBssList->Network[j].dot11Ssid, pBssList->Network[j].dot11BssType,
pBssList->Network[j].bSecurityEnabled,
NULL, &ppWlanBssList);
if (ERROR_SUCCESS == dwResult)
{
for (int k = 0; k < ppWlanBssList->dwNumberOfItems; k++)
{
printf(" %3 MAC Addr:");
printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
ppWlanBssList->wlanBssEntries[k].dot11Bssid[0],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[1],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[2],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[3],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[4],
ppWlanBssList->wlanBssEntries[k].dot11Bssid[5]
);
}
}
wprintf(L" %3 Signal Intensity:%5d\n",pBssList-Network[j].wlanSignalQuality);
}
}
return true;
敬请期待下集:Wlan之谜(三):玩转疯狂API
Wlan之谜(四):三维一体两栖登陆
上一篇:Wlan之谜(一)