0x00 說(shuō)在前面的廢話
2021年10月5日這一天注定是不尋常的一天......因?yàn)椤熬抻病卑l(fā)布了Windows 11。本人在第一時(shí)間裝了Windows 11。體驗(yàn)還算不錯(cuò),下面是windows 11的開(kāi)始菜單啦。感覺(jué)又要適應(yīng)一段時(shí)間了。但是發(fā)現(xiàn)了一個(gè)問(wèn)題,這貨!任務(wù)欄不能改!位!置!這難不倒我吧,,上網(wǎng)查資料發(fā)現(xiàn)可以通過(guò)修改注冊(cè)表來(lái)更改任務(wù)欄的位置??吹竭@里,要不咱們就用Rust來(lái)大干一場(chǎng),正好練習(xí)下Rust的winapi。后來(lái)......就有了這篇文章。
本文也正好借此機(jī)會(huì)說(shuō)下Rust使用winapi的一些坑。如果您是一直從事winapi開(kāi)發(fā)的大佬,懇請(qǐng)大佬批評(píng)改正。本人對(duì)winapi也不是很熟悉,且Rust版的winapi也沒(méi)有文檔,只能通過(guò)C++的文檔來(lái)寫(xiě)了,難免存在不足之處。

0x01 自定義windows11的任務(wù)欄位置
微軟雖然沒(méi)有提供修改任務(wù)欄位置的設(shè)置項(xiàng),但是仍然可以通過(guò)修改注冊(cè)表來(lái)達(dá)到改變?nèi)蝿?wù)欄的位置。操作注冊(cè)表前建議備份注冊(cè)表。打開(kāi)注冊(cè)表編輯器,定位到:\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3,然后雙擊 Settings 打開(kāi)。

在打開(kāi)的二進(jìn)制編輯器中,找到紅框標(biāo)注的 03(FE 下方的那個(gè)),將其修改為 00(左)、01(上)、02(右),接著使用軟媒魔方重啟 Windows 資源管理器,即可改變?nèi)蝿?wù)欄位置。

經(jīng)過(guò)本人的親測(cè),任務(wù)欄在上下方式?jīng)]有任何問(wèn)題的,但是在左右兩側(cè),會(huì)導(dǎo)致中間的圖標(biāo)顯示不出來(lái)。下面是效果圖。

0x02 操作注冊(cè)表的常用方法
要操作Windows注冊(cè)表一定需要winapi,本節(jié)課所使用的winapi庫(kù)是0.3.9版本(截至寫(xiě)這篇文章時(shí)是最新的)。操作注冊(cè)表無(wú)非就是增、刪、改、查這四個(gè)方法啦。在winapi里面分別對(duì)應(yīng)RegCreateKey、RegDeleteKey、RegSetValue、RegQueryValue,最后再加上一個(gè)創(chuàng)建方法RegOpenKey。
簡(jiǎn)單介紹下這幾個(gè)常用的相關(guān)方法吧。
RegCreateKeyExW
該方法是用來(lái)創(chuàng)建一個(gè)項(xiàng)。這個(gè)方法有9個(gè)參數(shù),不要被嚇到。有很多參數(shù)默認(rèn)就可以。第一個(gè)是HKEY類型,可以傳微軟默認(rèn)的5個(gè)值之一。這里以HKEY_CURRENT_USER為例。第二個(gè)參數(shù)是創(chuàng)建的項(xiàng)的名稱(該字段是LPCWSTR類型,后面會(huì)介紹如何構(gòu)建這個(gè)類型),第三到第五個(gè)參數(shù),以及第七個(gè)參數(shù)按照下方默認(rèn)來(lái)寫(xiě)即可。第六個(gè)參數(shù),是創(chuàng)建子鍵后的結(jié)果,是一個(gè)HKEY類型。
let mut hkey: HKEY = null_mut();
let mut lp: Vec<u16> = OsStr::new("Software\\360\\333").encode_wide().chain(once(0)).collect();
let create_result = RegCreateKeyExW(HKEY_CURRENT_USER,
lp.as_ptr(),
0,
null_mut(),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
null_mut(),
&mut hkey,
null_mut());
RegDeleteKeyExW
該方法是用來(lái)刪除一個(gè)項(xiàng)。請(qǐng)謹(jǐn)慎使用該方法,一旦刪除,將不可逆轉(zhuǎn)。這個(gè)方法有4個(gè)參數(shù),第一個(gè)參數(shù)同RegCreateKeyExW方法的第一個(gè)參數(shù)。第二個(gè)參數(shù)是要?jiǎng)h除項(xiàng)的名稱。第三和第四按照以下代碼默認(rèn)即可。
let mut lp: Vec<u16> = OsStr::new("Software\\360\\333").encode_wide().chain(once(0)).collect();
let result = RegDeleteKeyExW(HKEY_CURRENT_USER, lp.as_ptr(), KEY_ALL_ACCESS, 0);
RegSetValueExW
該方法是用來(lái)修改一個(gè)鍵值。請(qǐng)謹(jǐn)慎使用該方法,一旦修改,將不可逆轉(zhuǎn)。該方法有6個(gè)參數(shù),第一個(gè)參數(shù)是HKEY類型的參數(shù),通常傳遞RegOpenKey方法返回的參數(shù)。第二個(gè)參數(shù)是要修改值的鍵名。第三個(gè)參數(shù)默認(rèn)0即可。第四個(gè)參數(shù)是你要修改值的類型,通常有REG_SZ,REG_BINARY,REG_DWORD,REG_DWORD_LITTLE_ENDIAN,REG_DWORD_BIG_ENDIAN等10多種類型。第五個(gè)參數(shù)就是要修改的值了。第六個(gè)參數(shù)則是新值的占內(nèi)存的長(zhǎng)度了。
let mut lp: Vec<u16> = OsStr::new("Software\\360\\333").encode_wide().chain(once(0)).collect();
let mut val: Vec<u16> = OsStr::new("ABCD").encode_wide().chain(once(0)).collect();
let result = RegSetValueExW(hkey, key.as_ptr(), 0, REG_SZ, val.as_ptr() as *const u8, (size_of_val(&val) as u32));
RegQueryValueExW
該方法是用來(lái)查詢一個(gè)鍵的當(dāng)前值內(nèi)容。該方法也擁有6個(gè)參數(shù)。第一個(gè)參數(shù)是HKEY類型的參數(shù),通常傳遞RegOpenKey方法返回的參數(shù)。第二個(gè)參數(shù)是要修改值的鍵名稱。第三個(gè)參數(shù)模式為null_mut(),第四個(gè)參數(shù)是保存當(dāng)前查詢值的類型。第五個(gè)參數(shù)是保存當(dāng)前值的數(shù)據(jù)內(nèi)容。第六個(gè)參數(shù)是保存當(dāng)前數(shù)據(jù)的長(zhǎng)度。此方法需要調(diào)用兩次。第一次是僅獲取返回的數(shù)據(jù)長(zhǎng)度,第二次調(diào)用時(shí)收集數(shù)據(jù)。因此第一次調(diào)用時(shí),第五個(gè)參數(shù)可以為null_mut(),第二次調(diào)用時(shí)則是一個(gè)帶有長(zhǎng)度的數(shù)組了。
let mut dword: DWORD = 0;
let mut dtype: DWORD = 0;
//查詢
let status = RegQueryValueExW(*hkey,
lp.as_ptr(),
null_mut(),
&mut dtype,
null_mut(),
&mut dword);
let mut data_binary: Vec<u8> = vec![0; dword as usize];
if status == SEC_E_OK {
// 存在值
RegQueryValueExW(*hkey,
str_to_lpcwstr(key_name).as_ptr(),
null_mut(),
&mut dtype,
data_binary.as_mut_ptr(),
&mut dword);
}
RegOpenKeyW
該方法用來(lái)打開(kāi)一個(gè)注冊(cè)表項(xiàng)。這個(gè)方法很簡(jiǎn)單,該方法有三個(gè)參數(shù)。第一個(gè)參數(shù)是HKEY類型的參數(shù),第二個(gè)是子項(xiàng)的名稱,第三個(gè)是打開(kāi)后保存的HKEY結(jié)果
let mut hkey: HKEY = null_mut();
let mut lp: Vec<u16> = OsStr::new("Software\\360\\333").encode_wide().chain(once(0)).collect();
let status = RegOpenKeyW(HKEY_CURRENT_USER,
lp.as_ptr(),
&mut hkey);
0x03 小結(jié)
本節(jié)課簡(jiǎn)單介紹了下使用Rust來(lái)操作注冊(cè)表常用的幾個(gè)參數(shù)。其實(shí)跟C++大同小異,有一點(diǎn)兒要注意的是Windows的16字寬的編碼,下節(jié)再講解。另外我們離windows11注冊(cè)表修改的工具還比較遠(yuǎn),希望大家耐心讀文章。
0x04 關(guān)于本文源碼
完整的源碼,我將在該文章全部結(jié)束后放出。如果有什么不明白的可以關(guān)注公眾號(hào):《Rust學(xué)習(xí)日記》給我留言。當(dāng)然源碼也會(huì)通過(guò)公眾號(hào)給出喲~