Guest User

Untitled

a guest
Jul 19th, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.36 KB | None | 0 0
  1. /*
  2. Main.cpp
  3. */
  4. #include <iostream>
  5. #include "AquireInput.h"
  6. #include "Error.h"
  7. #include "Help.h"
  8. #include "RegAdd.h"
  9. #include "RegQuery.h"
  10.  
  11. int wmain(int argc, wchar_t* argv[])
  12. {
  13. RegBlock aVal;
  14. int result = getInput(argc, argv, aVal);
  15.  
  16. switch (result)
  17. {
  18. case REG_ADD: add(aVal); break;
  19. case REG_QUERY: query(aVal); break;
  20. case REG_DELETE: break;
  21. case REG_HELP_GENERAL:
  22. case REG_HELP_ADD:
  23. case REG_HELP_QUERY:
  24. case REG_HELP_DELETE: help(result); break;
  25. default: error(result); break;
  26. }
  27.  
  28. return 0;
  29. }
  30.  
  31. /*
  32. AquireInput.cpp
  33. */
  34. #include <queue>
  35. #include "AquireInput.h"
  36. #include "Help.h"
  37.  
  38. struct RegBlock
  39. {
  40. std::wstring lHkey = L"";
  41. std::wstring lHkeyPath = L"";
  42. std::wstring lValueName = L"";
  43. std::wstring lDataType = L"";
  44. std::wstring lData = L"";
  45. bool lViewed[12] = { false };
  46. std::map<std::string, bool> lOptions = {
  47. { "/k",false },
  48. { "/d",false },
  49. { "/s",false },
  50. { "/c",false },
  51. { "/e",false },
  52. { "/z",false },
  53. { "/f",false }
  54. };
  55. };
  56.  
  57. // Parameter handles
  58. #define V (0)
  59. #define VE (1)
  60. #define T (2)
  61. #define D (3)
  62. #define F (4)
  63. #define S (5)
  64. #define K (6)
  65. #define C (7)
  66. #define E (8)
  67. #define Z (9)
  68. #define VA (10)
  69.  
  70. uint8_t checkIdentifer(std::wstring arg, bool viewed[])
  71. {
  72. if (arg == L"/v" && !viewed[V])
  73. {
  74. viewed[VE] = true; // Deactivate value empty arg
  75. return V;
  76. }
  77. if (arg == L"/ve" && !viewed[VE])
  78. {
  79. viewed[V] = true; // Deactivate value specify arg
  80. return VE;
  81. }
  82.  
  83. if (arg == L"/k" && !viewed[K])
  84. {
  85. viewed[D] = true; // Deactivate data search arg
  86. return K;
  87. }
  88. if (arg == L"/d" && !viewed[D])
  89. {
  90. viewed[K] = true; // Deactivate key value search arg
  91. return D;
  92. }
  93.  
  94. if (arg == L"/t" && !viewed[T]) return T;
  95. if (arg == L"/f" && !viewed[F]) return F;
  96. if (arg == L"/s" && !viewed[S]) return S;
  97. if (arg == L"/c" && !viewed[C]) return C;
  98. if (arg == L"/e" && !viewed[E]) return E;
  99. if (arg == L"/z" && !viewed[Z]) return Z;
  100.  
  101. return L'x';
  102. }
  103.  
  104. bool validDataType(std::wstring aDataType)
  105. {
  106. if (getDataTypeMacro(aDataType) != NULL) return true;
  107. return false;
  108. }
  109.  
  110. bool validKeyName(std::wstring s)
  111. {
  112. // Test if a minimum string length has been met
  113. if (s.size() < 3) return false;
  114.  
  115. if (s.size() == 3)
  116. {
  117. if (s.substr(0, 3) == L"HKU") return true;
  118. return false;
  119. }
  120. else
  121. {
  122. std::wstring lHkey = s.substr(0, 4);
  123. if (lHkey == L"HKCR") return true;
  124. if (lHkey == L"HKCC") return true;
  125. if (lHkey == L"HKCU") return true;
  126. if (lHkey == L"HKLM") return true;
  127. if (lHkey.substr(0, 3) == L"HKU") return true;
  128.  
  129. return false;
  130. }
  131. }
  132.  
  133. bool setHKey(std::wstring s, RegBlock &aVal)
  134. {
  135. // Test if a minimum string length has been met
  136. if (s.size() < 3) return false;
  137.  
  138. // Addresses case in which user only input 'ADD HKU'
  139. if (s.size() == 3)
  140. {
  141. if (s.substr(0, 3) == L"HKU")
  142. {
  143. aVal.lHkey = L"HKU";
  144. }
  145. return true;
  146. }
  147. else
  148. {
  149.  
  150. std::wstring lHkey = s.substr(0, 4);
  151.  
  152. // Test if a lHkeyPath has been inputted
  153. if (s.size() > 4)
  154. {
  155. aVal.lHkeyPath = s.substr(5);
  156. }
  157.  
  158. if (lHkey == L"HKCR") aVal.lHkey = L"HKCR";
  159. if (lHkey == L"HKCC") aVal.lHkey = L"HKCC";
  160. if (lHkey == L"HKCU") aVal.lHkey = L"HKCU";
  161. if (lHkey == L"HKLM") aVal.lHkey = L"HKLM";
  162. if (lHkey.substr(0, 3) == L"HKU")
  163. {
  164. aVal.lHkey = L"HKU";
  165. if (s.size() > 4)
  166. {
  167. aVal.lHkeyPath = s.substr(4);
  168. }
  169. }
  170.  
  171. return true;
  172. }
  173. }
  174.  
  175. int getInput(int argc, wchar_t* argv[], RegBlock& aVal)
  176. {
  177. std::queue<std::wstring> lQueue;
  178. // Add argv values to lQueue
  179. for (int i = 1; i < argc; i++)
  180. {
  181. lQueue.push(argv[i]);
  182. }
  183.  
  184. if (lQueue.size() == 0) return MISSING_CORE_PARAMETER;
  185.  
  186. // Get action (ADD,DELETE,QUERY..ect);
  187. std::wstring lCurrentVal = lQueue.front();
  188. lQueue.pop();
  189.  
  190. // Guard against repeat parameter/sytax e.g /v Hello /ve /f /f
  191. //bool lViewed[12] = { false };
  192. #define lViewed (aVal.lViewed)
  193.  
  194. if (lCurrentVal == L"ADD")
  195. {
  196. if (lQueue.size() == 0) return MISSING_CORE_PARAMETER;
  197.  
  198. lCurrentVal = lQueue.front();
  199.  
  200. // Check if ADD HELP was requested
  201. if (lCurrentVal == L"/?") return REG_HELP_ADD;
  202.  
  203. // Check & Set HKEY value
  204. if (!validKeyName(lCurrentVal)) return NON_VALID_HKEY;
  205. setHKey(lCurrentVal, aVal);
  206. lQueue.pop();
  207.  
  208. // Check validity of parameter
  209. while (lQueue.size())
  210. {
  211. lCurrentVal = lQueue.front();
  212. lQueue.pop();
  213.  
  214. switch (checkIdentifer(lCurrentVal, lViewed))
  215. {
  216. case V: lViewed[V] = true;
  217. aVal.lValueName = lQueue.front();
  218. lQueue.pop();
  219. break;
  220. case VE: lViewed[VE] = true;
  221. break;
  222. case T: lViewed[T] = true;
  223. lCurrentVal = lQueue.front();
  224. if (!validDataType(lCurrentVal)) return NON_VALID_DATA_TYPE;
  225. aVal.lDataType = lCurrentVal;
  226. lQueue.pop();
  227. break;
  228. case D: lViewed[D] = true;
  229. aVal.lData = lQueue.front();
  230. lQueue.pop();
  231. break;
  232. case F: lViewed[F] = true;
  233. aVal.lOptions["/f"] = true;
  234. break;
  235. default: return UNKNOWN_PARAMETER;
  236. }
  237.  
  238. }
  239. return REG_ADD;
  240. }
  241.  
  242. if (lCurrentVal == L"QUERY")
  243. {
  244. if (lQueue.size() == 0) return MISSING_CORE_PARAMETER;
  245.  
  246. lCurrentVal = lQueue.front();
  247.  
  248. // Check if ADD HELP was requested
  249. if (lCurrentVal == L"/?") return REG_HELP_QUERY;
  250.  
  251. // Check & Set HKEY value
  252. if (!validKeyName(lCurrentVal)) return NON_VALID_HKEY;
  253. setHKey(lCurrentVal, aVal);
  254. lQueue.pop();
  255.  
  256. // Check validity of parameter
  257. while (lQueue.size())
  258. {
  259. lCurrentVal = lQueue.front();
  260. lQueue.pop();
  261.  
  262. switch (checkIdentifer(lCurrentVal, lViewed))
  263. {
  264. case V: lViewed[V] = true;
  265. aVal.lValueName = lQueue.front();
  266. lQueue.pop();
  267. break;
  268. case VE: lViewed[VE] = true;
  269. break;
  270. case S: lViewed[S] = true;
  271. aVal.lOptions["/s"] = true;
  272. break;
  273. case F: lViewed[F] = true;
  274. aVal.lOptions["/f"] = true;
  275. aVal.lData = lQueue.front();
  276. lQueue.pop();
  277. break;
  278. case K: lViewed[K] = true;
  279. aVal.lOptions["/k"] = true;
  280. break;
  281. case D: lViewed[D] = true;
  282. aVal.lOptions["/d"] = true;
  283. break;
  284. case C: lViewed[C] = true;
  285. aVal.lOptions["/c"] = true;
  286. break;
  287. case E: lViewed[E] = true;
  288. aVal.lOptions["/e"] = true;
  289. break;
  290. case T: lViewed[T] = true;
  291. lCurrentVal = lQueue.front();
  292. if (!validDataType(lCurrentVal)) return NON_VALID_DATA_TYPE;
  293. aVal.lDataType = lCurrentVal;
  294. lQueue.pop();
  295. break;
  296. case Z: lViewed[Z] = true;
  297. aVal.lOptions["/z"] = true;
  298. break;
  299. default: return UNKNOWN_PARAMETER;
  300. }
  301.  
  302. }
  303.  
  304. // Make sure that search options are not enabled without first specifing a search criteria
  305. if (lViewed[K] || lViewed[D] || lViewed[C] || lViewed[E] || lViewed[T])
  306. {
  307. if (!lViewed[F]) return UNKNOWN_PARAMETER;
  308. }
  309.  
  310. return REG_QUERY;
  311. }
  312.  
  313. if (lCurrentVal == L"DELETE")
  314. {
  315. return REG_DELETE;
  316. }
  317.  
  318. if (lCurrentVal == L"/?")
  319. {
  320. return REG_HELP_GENERAL;
  321. }
  322. return UNKNOWN_ACTION;
  323. }
  324.  
  325.  
  326. /*
  327. RegQuery.cpp
  328. */
  329. #include "RegQuery.h"
  330. #include <queue>
  331. #include <iomanip>
  332. #include <string>
  333. #include <io.h>
  334. #include <fcntl.h>
  335. #include <algorithm>
  336. #include <fstream>
  337.  
  338. #define MAX_KEY_LENGTH 255
  339. #define MAX_VALUE_NAME 32786
  340. #define MAX_DATA_VALUE 2000000
  341. std::wstring NULLWST = L""; // Placeholder null value
  342.  
  343. inline unsigned hexValidInt(int aVal)
  344. {
  345. if (aVal < 0)
  346. {
  347. aVal += 256;
  348. return aVal;
  349. }
  350. return aVal;
  351. }
  352.  
  353. template <typename I> std::string n2hexstr(I w, size_t hex_len = 2) {
  354. static const char* digits = "0123456789ABCDEF";
  355. std::string rc(hex_len, '0');
  356. for (size_t i = 0, j = (hex_len - 1) * 4; i < hex_len; ++i, j -= 4)
  357. {
  358. rc[i] = digits[(w >> j) & 0x0f];
  359. }
  360. // Corrects the order of the hex numbers e.g 34FE is corrected to FE34
  361. std::swap_ranges(std::begin(rc)+2, std::end(rc), std::begin(rc));
  362. return rc;
  363. }
  364.  
  365. inline unsigned int convertData(DWORD &aRegType, DWORD &aDataLength, wchar_t *aData, std::wstring &aDataResult)
  366. {
  367. std::wstring lDataResult;
  368. if (aRegType == REG_DWORD ||
  369. aRegType == REG_QWORD ||
  370. aRegType == REG_DWORD_LITTLE_ENDIAN ||
  371. aRegType == REG_QWORD_LITTLE_ENDIAN ||
  372. aRegType == REG_DWORD_BIG_ENDIAN)
  373. {
  374. // Reverse loop
  375. for (int i = (aDataLength * 0.5) - 1; i >= 0; i--)
  376. {
  377. if (aData[i] == 0) continue;
  378. lDataResult += convertToWstr(n2hexstr(hexValidInt(aData[i]),2));
  379. }
  380. }
  381.  
  382. if (aRegType == REG_BINARY || aRegType == REG_NONE)
  383. {
  384. for (int i = 0; i < (aDataLength * 0.5); i++)
  385. {
  386. lDataResult += convertToWstr(n2hexstr(hexValidInt(aData[i]),4));
  387. }
  388. }
  389.  
  390. if (aRegType == REG_SZ || aRegType == REG_MULTI_SZ)
  391. {
  392. int lEnd = (aDataLength * 0.5) - 1;
  393.  
  394. // Avoid adding trailing zero
  395. if (aRegType == REG_MULTI_SZ)
  396. {
  397. lEnd = (aDataLength * 0.5) - 2;
  398. }
  399.  
  400. for (int i = 0; i < lEnd; i++)
  401. {
  402. if (aData[i] == 0)
  403. {
  404. lDataResult += L"\0";
  405. continue;
  406. }
  407.  
  408. lDataResult += aData[i];
  409. }
  410. }
  411.  
  412. aDataResult = lDataResult;
  413. return 0;
  414. }
  415.  
  416. struct RegValue
  417. {
  418. std::wstring lValueName;
  419. unsigned int lRegType;
  420. std::wstring lDataValue;
  421.  
  422. };
  423.  
  424. inline std::wstring constructKeyPath(std::wstring &aHkeyPath, std::wstring &aSubKey)
  425. {
  426. std::wstring lSlash = L"\";
  427. std::wstring lFullPath;
  428.  
  429. if (aSubKey == L"")
  430. {
  431. lFullPath = aHkeyPath;
  432. }
  433. else
  434. {
  435. lFullPath = aHkeyPath + lSlash + aSubKey;
  436. }
  437.  
  438. return lFullPath;
  439. }
  440.  
  441. inline unsigned int getValueNameList(HKEY hKey, std::wstring &aHkeyPath, std::wstring &aSubKey, std::queue<std::wstring> &aValueList)
  442. {
  443. std::wstring lFullPath = constructKeyPath(aHkeyPath, aSubKey);
  444. LPCTSTR lpSubKey = lFullPath.c_str();
  445.  
  446. int lResult = RegOpenKeyEx(
  447. hKey,
  448. lpSubKey,
  449. 0, //add var
  450. KEY_QUERY_VALUE, //add var
  451. &hKey
  452. );
  453.  
  454. if (lResult != ERROR_SUCCESS)
  455. {
  456. return lResult;
  457. }
  458.  
  459. // Variables related to RegEnumValue
  460. LPDWORD lpReserved = NULL;
  461. LPDWORD lpType = NULL;
  462. LPBYTE lpData = NULL;
  463. LPDWORD lpcbData = NULL;
  464. DWORD dwIndex = 0;
  465.  
  466. // Avoid adding lpValueName initial value
  467. bool lSkip = true;
  468.  
  469. while (lResult != ERROR_NO_MORE_ITEMS)
  470. {
  471. wchar_t lpValueName[MAX_VALUE_NAME];
  472. DWORD lpcchValueName = MAX_VALUE_NAME;
  473.  
  474. // Add the list of value names to a vector list
  475. if (!lSkip)
  476. {
  477. aValueList.push(lpValueName);
  478. }
  479. else
  480. {
  481. lSkip = false;
  482. }
  483.  
  484. lResult = RegEnumValue(
  485. hKey,
  486. dwIndex,
  487. lpValueName,
  488. &lpcchValueName,
  489. lpReserved,
  490. lpType,
  491. lpData,
  492. lpcbData
  493. );
  494.  
  495. dwIndex++;
  496.  
  497. // Return an error if lResult is not an acceptable error
  498. if (lResult != ERROR_SUCCESS && lResult != ERROR_NO_MORE_ITEMS)
  499. {
  500. RegCloseKey(hKey);
  501. return lResult;
  502. }
  503. }
  504.  
  505. //Close key
  506. RegCloseKey(hKey);
  507.  
  508. return lResult = 0;
  509. }
  510.  
  511. inline unsigned int getSubKeyList(HKEY hKey, std::wstring &aHkeyPath, std::wstring &aSubKey, std::deque<std::wstring> &aSubKeyList)
  512. {
  513. std::wstring lFullPath = constructKeyPath(aHkeyPath, aSubKey);
  514. LPCTSTR lpSubKey = lFullPath.c_str();
  515.  
  516. DWORD i, lResult;
  517. lResult = RegOpenKeyEx(
  518. hKey,
  519. lpSubKey,
  520. 0,
  521. KEY_READ,
  522. &hKey
  523. );
  524.  
  525. TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
  526. DWORD cbName; // size of name string
  527. TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
  528. DWORD cchClassName = MAX_PATH; // size of class string
  529. DWORD cSubKeys = 0; // number of subkeys
  530. DWORD cbMaxSubKey; // longest subkey size
  531. DWORD cchMaxClass; // longest class string
  532. DWORD cValues; // number of values for key
  533. DWORD cchMaxValue; // longest value name
  534. DWORD cbMaxValueData; // longest value data
  535. DWORD cbSecurityDescriptor; // size of security descriptor
  536. FILETIME ftLastWriteTime; // last write time
  537.  
  538.  
  539.  
  540. TCHAR achValue[MAX_VALUE_NAME];
  541. DWORD cchValue = MAX_VALUE_NAME;
  542.  
  543. // Get the class name and the value count.
  544. lResult = RegQueryInfoKey(
  545. hKey, // key handle
  546. achClass, // buffer for class name
  547. &cchClassName, // size of class string
  548. NULL, // reserved
  549. &cSubKeys, // number of subkeys
  550. &cbMaxSubKey, // longest subkey size
  551. &cchMaxClass, // longest class string
  552. &cValues, // number of values for this key
  553. &cchMaxValue, // longest value name
  554. &cbMaxValueData, // longest value data
  555. &cbSecurityDescriptor, // security descriptor
  556. &ftLastWriteTime); // last write time
  557.  
  558.  
  559. // Enumerate the subkeys, until RegEnumKeyEx fails.
  560. if (cSubKeys)
  561. {
  562. for (i = 0; i<cSubKeys; i++)
  563. {
  564. cbName = MAX_KEY_LENGTH;
  565. lResult = RegEnumKeyEx(hKey, i,
  566. achKey,
  567. &cbName,
  568. NULL,
  569. NULL,
  570. NULL,
  571. &ftLastWriteTime);
  572. if (lResult == ERROR_SUCCESS)
  573. {
  574. // Attach parent key to child sub keys
  575. // e.g: key01/subkey01
  576. std::wstring lRelativePath = achKey;
  577. if (aSubKey != L"")
  578. {
  579. lRelativePath = aSubKey + L"\" + achKey;
  580. }
  581.  
  582. aSubKeyList.push_back(lRelativePath);
  583. }
  584. }
  585. }
  586.  
  587. //Close key
  588. RegCloseKey(hKey);
  589.  
  590. return lResult;
  591. }
  592.  
  593. inline unsigned int getValueData(HKEY aHkey, std::wstring &aHkeyPath, std::wstring &aSubKey, std::wstring &aValueName, RegValue &aValueData)
  594. {
  595. std::wstring lFullPath = constructKeyPath(aHkeyPath, aSubKey);
  596. LPCTSTR lSubKey = lFullPath.c_str();
  597. LPCTSTR lValueName = aValueName.c_str();
  598.  
  599. DWORD dwFlags = RRF_RT_ANY;
  600. DWORD pdwType;
  601. wchar_t *pvData = new wchar_t[MAX_DATA_VALUE];
  602. DWORD pcbData = MAX_DATA_VALUE;
  603.  
  604. int lResult = RegGetValue(
  605. aHkey,
  606. lSubKey,
  607. lValueName,
  608. dwFlags,
  609. &pdwType,
  610. pvData,
  611. &pcbData
  612. );
  613.  
  614. // Check if lResult is okay
  615. if (lResult != ERROR_SUCCESS)
  616. {
  617. delete[] pvData;
  618. return lResult;
  619. }
  620.  
  621. if (pcbData >= MAX_DATA_VALUE)
  622. {
  623. std::cout << "Data Value Exceeded! Registery data value > 2MB!" << std::endl;
  624. return lResult;
  625. }
  626.  
  627. // Convert data values & Store results
  628. std::wstring lDataValue;
  629. convertData(pdwType, pcbData, pvData, lDataValue);
  630. aValueData.lDataValue = lDataValue;
  631. aValueData.lValueName = lValueName;
  632. aValueData.lRegType = pdwType;
  633.  
  634. delete[] pvData;
  635. return lResult;
  636. }
  637.  
  638. /*
  639. Show related functions
  640. */
  641. inline std::wstring getHkeyStringName(HKEY aHkey)
  642. {
  643. if (aHkey == HKEY_CLASSES_ROOT) return L"HKEY_CLASSES_ROOT\";
  644. if (aHkey == HKEY_CURRENT_CONFIG) return L"HKEY_CURRENT_CONFIG\";
  645. if (aHkey == HKEY_CURRENT_USER) return L"HKEY_CURRENT_USER\";
  646. if (aHkey == HKEY_LOCAL_MACHINE) return L"HKEY_LOCAL_MACHINE\";
  647. if (aHkey == HKEY_USERS) return L"HKEY_USERS\";
  648.  
  649. return L"NULL";
  650. }
  651.  
  652. inline std::wstring getDataTypeStringName(unsigned int &aDataType)
  653. {
  654. if (aDataType == REG_SZ) return L"REG_SZ";
  655. if (aDataType == REG_MULTI_SZ) return L"REG_MULTI_SZ";
  656. if (aDataType == REG_EXPAND_SZ) return L"REG_EXPAND_SZ";
  657.  
  658. if (aDataType == REG_DWORD) return L"REG_DWORD";
  659. if (aDataType == REG_DWORD_BIG_ENDIAN) return L"REG_DWORD_BIG_ENDIAN";
  660. if (aDataType == REG_DWORD_LITTLE_ENDIAN) return L"REG_DWORD_LITTLE_ENDIAN";
  661.  
  662. if (aDataType == REG_QWORD) return L"REG_QWORD";
  663. if (aDataType == REG_QWORD_LITTLE_ENDIAN) return L"REG_QWORD_LITTLE_ENDIAN";
  664.  
  665. if (aDataType == REG_BINARY) return L"REG_BINARY";
  666.  
  667. if (aDataType == REG_NONE) return L"REG_NONE";
  668.  
  669. return L"NULL";
  670. }
  671.  
  672. unsigned int WriteToConsole(std::wstring &aString)
  673. {
  674. int lResult = ERROR_SUCCESS;
  675. static HANDLE lConsoleAccess = GetStdHandle(STD_OUTPUT_HANDLE);
  676.  
  677. lResult = WriteConsoleW(
  678. lConsoleAccess,
  679. aString.c_str(),
  680. aString.size(),
  681. NULL,
  682. NULL
  683. );
  684.  
  685. return lResult;
  686. }
  687.  
  688. // Testing
  689. //#define __nonEnglishMode
  690. //#define __writeToDisk
  691.  
  692. #if defined (__writeToDisk)
  693. std::wofstream file;
  694. #endif
  695.  
  696. inline void show(HKEY aHkey, std::wstring &aHkeyPath, std::wstring &aSubKey, RegValue &aValueData, bool aDisplayPath, bool aDisplayValue, bool aLastItem)
  697. {
  698. // Display Key Path HKEY/key/key..ect
  699. if (aDisplayPath)
  700. {
  701. std::wstring lSlash = L"\";
  702. std::wstring lFullPath;
  703.  
  704. #if defined (__writeToDisk)
  705. file << L"n";
  706. #endif
  707.  
  708. // Only attach subkey to path name if it is supplied
  709. if (aSubKey == L"")
  710. {
  711. lFullPath = getHkeyStringName(aHkey) + aHkeyPath + L"n";
  712. }
  713. else
  714. {
  715. lFullPath = getHkeyStringName(aHkey) + aHkeyPath + lSlash + aSubKey + L"n";
  716. }
  717.  
  718. //fwprintf(stdout, L"%s",lFullPath.c_str());
  719. WriteToConsole(lFullPath);
  720. #if defined (__writeToDisk)
  721. file << lFullPath;
  722. #endif
  723.  
  724. }
  725.  
  726. if (aDisplayValue)
  727. {
  728. // Show registry value name
  729. std::wstring lValueName = (aValueData.lValueName);
  730. if (lValueName == TEXT("")) lValueName = TEXT("(Default)");
  731.  
  732. // Show registry type
  733. std::wstring lDataType = getDataTypeStringName(aValueData.lRegType);
  734. std::wstring lDataValue;
  735.  
  736. // Show registry data
  737. if (lDataType == L"REG_DWORD" ||
  738. lDataType == L"REG_QWORD" ||
  739. lDataType == L"REG_DWORD_LITTLE_ENDIAN" ||
  740. lDataType == L"REG_QWORD_LITTLE_ENDIAN" ||
  741. lDataType == L"REG_DWORD_BIG_ENDIAN")
  742. {
  743. lDataValue = L"0x0" + (aValueData.lDataValue);
  744. }
  745. else
  746. {
  747. lDataValue = (aValueData.lDataValue);
  748. }
  749.  
  750. std::wstring lKeyValue = L" " + lValueName + L" " + lDataType + L" " + lDataValue + L"n";
  751. //fwprintf(stdout,L"%s",lKeyValue.c_str());
  752. WriteToConsole(lKeyValue);
  753. #if defined (__writeToDisk)
  754. file << lKeyValue;
  755. #endif
  756. }
  757.  
  758. #if defined (__writeToDisk)
  759. if (file.fail())
  760. {
  761. file.clear();
  762. }
  763. #endif
  764. }
  765.  
  766. DWORD getDataTypeFilterMacro(std::string &aDataType)
  767. {
  768. if (aDataType == "REG_SZ") return RRF_RT_REG_SZ;
  769. if (aDataType == "REG_MULTI_SZ") return RRF_RT_REG_MULTI_SZ;
  770. if (aDataType == "REG_EXPAND_SZ") return RRF_RT_REG_EXPAND_SZ;
  771.  
  772. if (aDataType == "REG_DWORD") return RRF_RT_DWORD;
  773. if (aDataType == "REG_DWORD_BIG_ENDIAN") return RRF_RT_DWORD;
  774. if (aDataType == "REG_DWORD_LITTLE_ENDIAN") return RRF_RT_DWORD;
  775.  
  776. if (aDataType == "REG_QWORD") return RRF_RT_QWORD;
  777. if (aDataType == "REG_QWORD_LITTLE_ENDIAN") return RRF_RT_QWORD;
  778.  
  779. if (aDataType == "REG_BINARY") return RRF_RT_REG_BINARY;
  780. if (aDataType == "REG_NONE") return RRF_RT_REG_NONE;
  781.  
  782. return RRF_RT_ANY;
  783. }
  784.  
  785. bool isMatch(RegValue &aRegValueData, std::wstring &aDataType, std::wstring &aSearchItem, std::wstring &aKeyName, bool lCaseSensitive = false, bool lExactMatch = false, bool aSearchKeyOnly = false, bool aSearchDataOnly = false)
  786. {
  787. bool lResult = false;
  788. std::wstring lSearchItem = aSearchItem;
  789. std::wstring lValueName = aRegValueData.lValueName;
  790. std::wstring lDataValue = aRegValueData.lDataValue;
  791. std::wstring lKeyName = aKeyName;
  792. // Convert to lowercase
  793. if (!lCaseSensitive || !lExactMatch)
  794. {
  795. std::transform(lSearchItem.begin(), lSearchItem.end(), lSearchItem.begin(), ::tolower);
  796. std::transform(lValueName.begin(), lValueName.end(), lValueName.begin(), ::tolower);
  797. std::transform(lDataValue.begin(), lDataValue.end(), lDataValue.begin(), ::tolower);
  798. std::transform(lKeyName.begin(), lKeyName.end(), lKeyName.begin(), ::tolower);
  799. }
  800.  
  801. // Search Key Names
  802. if (aSearchKeyOnly)
  803. {
  804. // Split and store the last key
  805. // ...MyCo//Key1//Key3 ->> Key3
  806. auto const pos = lKeyName.find_last_of('\');
  807. lKeyName = lKeyName.substr(pos + 1);
  808.  
  809. if (lKeyName == lSearchItem)
  810. {
  811. return true;
  812. }
  813.  
  814. return false;
  815. }
  816.  
  817. // Search Data
  818. if (aSearchDataOnly)
  819. {
  820. if (lDataValue == lSearchItem)
  821. {
  822. return true;
  823. }
  824.  
  825. return false;
  826. }
  827.  
  828. // Search both key name and data value
  829. if (!aSearchKeyOnly && !aSearchDataOnly)
  830. {
  831. if (lValueName == lSearchItem)
  832. {
  833. return true;
  834. }
  835.  
  836. if (lDataValue == lSearchItem)
  837. {
  838. return true;
  839. }
  840.  
  841. return false;
  842. }
  843.  
  844. return false;
  845. }
  846.  
  847. bool query(RegBlock &aVal)
  848. {
  849. int lResult;
  850.  
  851. #if defined (__writeToDisk)
  852. file.open("screen_output.txt", std::wofstream::app | std::wofstream::in);
  853. #endif
  854.  
  855. // Variables related to Queries/Find
  856. HKEY hkey = getHkeyMacro(aVal.lHkey);
  857. std::wstring lHkeyPath = aVal.lHkeyPath;
  858. bool lValueNameEmpty = aVal.lValueName.empty();
  859. bool lFind = aVal.lOptions["/f"];
  860. bool lSearchRecursive = aVal.lOptions["/s"];
  861. bool lFilterDataType = !(aVal.lDataType.empty());
  862. bool lCaseSensitive = aVal.lOptions["/c"];
  863. bool lExactMatch = aVal.lOptions["/e"];
  864. bool lSearchKeyOnly = aVal.lOptions["/k"];
  865. bool lSearchDataOnly = aVal.lOptions["/d"];
  866.  
  867. // Specify the search value to use, either the key name or search param input
  868. std::wstring lSearchItem = aVal.lData;
  869. if (!lValueNameEmpty)
  870. {
  871. lSearchItem = aVal.lValueName;
  872. }
  873.  
  874. std::deque<std::wstring> lSubKeyList;
  875. std::queue<std::wstring> lValueList;
  876.  
  877. // Get the list of value names if none is provided
  878. if (lValueNameEmpty)
  879. {
  880. lResult = getValueNameList(hkey, lHkeyPath, NULLWST, lValueList);
  881.  
  882. if (lResult != ERROR_SUCCESS)
  883. {
  884. error(lResult);
  885. return false;
  886. }
  887. }
  888. else
  889. {
  890. std::wstring lValueName = aVal.lValueName;
  891. lValueList.push(lValueName);
  892. }
  893.  
  894. // Get inital list of sub keys
  895. lResult = getSubKeyList(hkey, lHkeyPath, NULLWST, lSubKeyList);
  896.  
  897. if (lResult != ERROR_SUCCESS)
  898. {
  899. error(lResult);
  900. return false;
  901. }
  902.  
  903. RegValue lRegValueData;
  904. std::wstring lCurrentSubKey = NULLWST;
  905. std::wstring lCurrentValue = NULLWST;
  906. unsigned int lMatchTotal = 0;
  907.  
  908. // Allows for the last subkey within the dequeue to be shown
  909. lSubKeyList.push_back(L"End");
  910.  
  911. bool lDisplayPath = false;
  912. bool lDisplayValue = true;
  913. bool lNewLine = false;
  914. bool lMatch = false;
  915.  
  916. while (lSubKeyList.size())
  917. {
  918. // Search and Display keys when searching in KEY ONLY mode
  919. if (lSearchKeyOnly)
  920. {
  921. lMatch = isMatch(
  922. lRegValueData,
  923. aVal.lDataType,
  924. lSearchItem,
  925. lCurrentSubKey,
  926. lCaseSensitive,
  927. lExactMatch,
  928. lSearchKeyOnly,
  929. lSearchDataOnly
  930. );
  931.  
  932. if (lMatch)
  933. {
  934. lDisplayPath = true;
  935. lDisplayValue = false;
  936. show(hkey, lHkeyPath, lCurrentSubKey, lRegValueData, lDisplayPath, lDisplayValue, false);
  937. lDisplayPath = false;
  938. lDisplayValue = true;
  939.  
  940. lNewLine = true;
  941. lMatchTotal++;
  942. }
  943. }
  944.  
  945. // Display the key path in the case of empty key && list keys when not in recursive/search mode
  946. if (lValueList.size() == 0 && !(lFilterDataType || lFind) && lValueNameEmpty)
  947. {
  948. show(hkey, lHkeyPath, lCurrentSubKey, lRegValueData, true, false, false);
  949. }
  950. else
  951. {
  952. lDisplayPath = true;
  953. }
  954.  
  955. while (lValueList.size() && !lSearchKeyOnly)
  956. {
  957. lCurrentValue = lValueList.front();
  958. lValueList.pop();
  959. lResult = getValueData(hkey, lHkeyPath, lCurrentSubKey, lCurrentValue, lRegValueData);
  960.  
  961. if (lResult != ERROR_SUCCESS)
  962. {
  963. error(lResult);
  964. return false;
  965. }
  966.  
  967. if (lFind || lFilterDataType)
  968. {
  969. lMatch = isMatch(
  970. lRegValueData,
  971. aVal.lDataType,
  972. lSearchItem,
  973. lCurrentSubKey,
  974. lCaseSensitive,
  975. lExactMatch,
  976. lSearchKeyOnly,
  977. lSearchDataOnly
  978. );
  979.  
  980. if (lMatch)
  981. {
  982. if (lSearchKeyOnly)
  983. {
  984. lDisplayPath = true;
  985. lDisplayValue = false;
  986. }
  987. show(hkey, lHkeyPath, lCurrentSubKey, lRegValueData, lDisplayPath, lDisplayValue, false);
  988. lDisplayPath = false;
  989. lDisplayValue = true;
  990.  
  991. lMatchTotal++;
  992. lNewLine = true;
  993. }
  994. }
  995. else
  996. {
  997. show(hkey, lHkeyPath, lCurrentSubKey, lRegValueData, lDisplayPath, lDisplayValue, false);
  998. lDisplayPath = false;
  999. }
  1000. }
  1001.  
  1002. if (lSearchRecursive && !(lFilterDataType || lFind))
  1003. {
  1004. lNewLine = true;
  1005. }
  1006.  
  1007. if (lNewLine)
  1008. {
  1009. fwprintf(stdout, L"n");
  1010. lNewLine = false;
  1011. }
  1012.  
  1013. // Remove visted Sub-Key from deque
  1014. lCurrentSubKey = lSubKeyList.front();
  1015. lSubKeyList.pop_front();
  1016.  
  1017. if (lSearchRecursive && lCurrentSubKey != L"End")
  1018. {
  1019. // If the parent key contains sub-keys, add them to lSubKeyList,
  1020. // in the order they were retrieved from RegEnumEx.
  1021. std::deque<std::wstring> lTemp;
  1022. lResult = getSubKeyList(hkey, lHkeyPath, lCurrentSubKey, lTemp);
  1023.  
  1024. while (lTemp.size())
  1025. {
  1026. lSubKeyList.push_front(lTemp.back());
  1027. lTemp.pop_back();
  1028. }
  1029.  
  1030. // A non-error. Error: "Invalid Handle"
  1031. // This error code just states that the current key being accessed
  1032. // does not contain any sub-keys.
  1033. if (lResult == 6) lResult = 0;
  1034.  
  1035. if (lResult != ERROR_SUCCESS)
  1036. {
  1037. error(lResult);
  1038. return false;
  1039. }
  1040.  
  1041. // Get the current keys value names
  1042. if (!lSearchKeyOnly)
  1043. {
  1044. lResult = getValueNameList(hkey, lHkeyPath, lCurrentSubKey, lValueList);
  1045.  
  1046. // Ignore key values that cannot be accessed. Error "Access Denied"
  1047. // Keys cannot be accessed in regedit (admin), so this is a UAC issue.
  1048. if (lResult == 5) lResult = 0;
  1049.  
  1050. if (lResult != ERROR_SUCCESS)
  1051. {
  1052. error(lResult);
  1053. return false;
  1054. }
  1055. }
  1056. }
  1057. }
  1058.  
  1059. #if defined (__writeToDisk)
  1060. file.close();
  1061. #endif
  1062.  
  1063. if (lFind || lFilterDataType)
  1064. {
  1065. std::cout << "End of search : " << lMatchTotal << " match(es) found." << std::endl;
  1066. }
  1067.  
  1068. return true;
  1069. }
Add Comment
Please, Sign In to add comment