Advertisement
Josiahiscool73

full ai Fortnite driver in C++

Mar 16th, 2025
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.37 KB | None | 0 0
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <vector>
  4. #include <string>
  5. #include <sstream>
  6. #include <iomanip>
  7. #include <thread>
  8. #include <chrono>
  9. #include <unordered_map>
  10.  
  11. // Define IOCTLs for driver communication
  12. #define IOCTL_READ_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  13. #define IOCTL_WRITE_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
  14. #define IOCTL_GET_PROCESS_BASE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
  15. #define IOCTL_GET_MODULE_BASE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
  16.  
  17. // Structure for memory operations
  18. typedef struct _MEMORY_STRUCT {
  19. ULONG64 Address; // Target memory address
  20. ULONG Size; // Size of data to read/write
  21. UCHAR* Buffer; // Buffer for data transfer
  22. ULONG ProcessId; // Process ID for operation
  23. } MEMORY_STRUCT, *PMEMORY_STRUCT;
  24.  
  25. // Structure for module base address retrieval
  26. typedef struct _MODULE_STRUCT {
  27. ULONG ProcessId;
  28. WCHAR ModuleName[260];
  29. ULONG64 BaseAddress;
  30. } MODULE_STRUCT, *PMODULE_STRUCT;
  31.  
  32. // Offset cache to store discovered offsets
  33. std::unordered_map<std::string, ULONG64> offsetCache;
  34.  
  35. // Global variables
  36. HANDLE hDevice = INVALID_HANDLE_VALUE;
  37. ULONG targetProcessId = 0;
  38. ULONG64 processBaseAddress = 0;
  39. bool isRunning = true;
  40.  
  41. // Function prototypes
  42. bool InitializeDriver();
  43. void CloseDriver();
  44. bool ReadMemory(ULONG64 address, void* buffer, SIZE_T size);
  45. bool WriteMemory(ULONG64 address, void* buffer, SIZE_T size);
  46. ULONG64 GetProcessBaseAddress(ULONG processId);
  47. ULONG64 GetModuleBaseAddress(ULONG processId, const wchar_t* moduleName);
  48. void MonitorValue(ULONG64 address, SIZE_T size, int interval);
  49. void DisplayMenu();
  50. void ProcessCommand(const std::string& command);
  51. std::vector<std::string> SplitString(const std::string& input, char delimiter);
  52. std::string ToLowerCase(const std::string& input);
  53. ULONG64 ParseHexAddress(const std::string& hexString);
  54. void PrintMemory(UCHAR* buffer, SIZE_T size, ULONG64 address);
  55. void ScanForValue(const std::string& valueType, const std::string& value);
  56.  
  57. int main() {
  58. std::cout << "========================================\n";
  59. std::cout << "= Enhanced Memory Access Tool =\n";
  60. std::cout << "========================================\n\n";
  61.  
  62. if (!InitializeDriver()) {
  63. std::cout << "Press any key to exit...\n";
  64. std::cin.get();
  65. return 1;
  66. }
  67.  
  68. std::cout << "Driver initialized successfully!\n\n";
  69.  
  70. std::string command;
  71. DisplayMenu();
  72.  
  73. while (isRunning) {
  74. std::cout << "\n> ";
  75. std::getline(std::cin, command);
  76. ProcessCommand(command);
  77. }
  78.  
  79. CloseDriver();
  80. return 0;
  81. }
  82.  
  83. bool InitializeDriver() {
  84. hDevice = CreateFileW(L"\\\\.\\FortPenTest", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
  85.  
  86. if (hDevice == INVALID_HANDLE_VALUE) {
  87. std::cout << "Failed to open driver device: " << GetLastError() << std::endl;
  88. std::cout << "Make sure the driver is properly installed and running.\n";
  89. return false;
  90. }
  91.  
  92. return true;
  93. }
  94.  
  95. void CloseDriver() {
  96. if (hDevice != INVALID_HANDLE_VALUE) {
  97. CloseHandle(hDevice);
  98. hDevice = INVALID_HANDLE_VALUE;
  99. }
  100. }
  101.  
  102. bool ReadMemory(ULONG64 address, void* buffer, SIZE_T size) {
  103. if (hDevice == INVALID_HANDLE_VALUE || targetProcessId == 0) {
  104. std::cout << "Driver not initialized or process not selected.\n";
  105. return false;
  106. }
  107.  
  108. MEMORY_STRUCT mem = { address, static_cast<ULONG>(size), static_cast<UCHAR*>(buffer), targetProcessId };
  109. DWORD bytesReturned;
  110.  
  111. if (!DeviceIoControl(hDevice, IOCTL_READ_MEMORY, &mem, sizeof(mem), &mem, sizeof(mem), &bytesReturned, nullptr)) {
  112. std::cout << "Memory read failed: " << GetLastError() << std::endl;
  113. return false;
  114. }
  115.  
  116. return true;
  117. }
  118.  
  119. bool WriteMemory(ULONG64 address, void* buffer, SIZE_T size) {
  120. if (hDevice == INVALID_HANDLE_VALUE || targetProcessId == 0) {
  121. std::cout << "Driver not initialized or process not selected.\n";
  122. return false;
  123. }
  124.  
  125. MEMORY_STRUCT mem = { address, static_cast<ULONG>(size), static_cast<UCHAR*>(buffer), targetProcessId };
  126. DWORD bytesReturned;
  127.  
  128. if (!DeviceIoControl(hDevice, IOCTL_WRITE_MEMORY, &mem, sizeof(mem), &mem, sizeof(mem), &bytesReturned, nullptr)) {
  129. std::cout << "Memory write failed: " << GetLastError() << std::endl;
  130. return false;
  131. }
  132.  
  133. return true;
  134. }
  135.  
  136. ULONG64 GetProcessBaseAddress(ULONG processId) {
  137. if (hDevice == INVALID_HANDLE_VALUE) {
  138. std::cout << "Driver not initialized.\n";
  139. return 0;
  140. }
  141.  
  142. DWORD bytesReturned;
  143. ULONG64 baseAddress = 0;
  144.  
  145. if (!DeviceIoControl(
  146. hDevice,
  147. IOCTL_GET_PROCESS_BASE,
  148. &processId,
  149. sizeof(processId),
  150. &baseAddress,
  151. sizeof(baseAddress),
  152. &bytesReturned,
  153. nullptr
  154. )) {
  155. std::cout << "Failed to get process base address: " << GetLastError() << std::endl;
  156. return 0;
  157. }
  158.  
  159. return baseAddress;
  160. }
  161.  
  162. ULONG64 GetModuleBaseAddress(ULONG processId, const wchar_t* moduleName) {
  163. if (hDevice == INVALID_HANDLE_VALUE) {
  164. std::cout << "Driver not initialized.\n";
  165. return 0;
  166. }
  167.  
  168. MODULE_STRUCT moduleInfo = { 0 };
  169. moduleInfo.ProcessId = processId;
  170. wcscpy_s(moduleInfo.ModuleName, moduleName);
  171.  
  172. DWORD bytesReturned;
  173.  
  174. if (!DeviceIoControl(
  175. hDevice,
  176. IOCTL_GET_MODULE_BASE,
  177. &moduleInfo,
  178. sizeof(moduleInfo),
  179. &moduleInfo,
  180. sizeof(moduleInfo),
  181. &bytesReturned,
  182. nullptr
  183. )) {
  184. std::cout << "Failed to get module base address: " << GetLastError() << std::endl;
  185. return 0;
  186. }
  187.  
  188. return moduleInfo.BaseAddress;
  189. }
  190.  
  191. void MonitorValue(ULONG64 address, SIZE_T size, int interval) {
  192. std::cout << "Monitoring address 0x" << std::hex << address << " (Press Ctrl+C to stop)...\n";
  193. std::vector<UCHAR> buffer(size, 0);
  194. std::vector<UCHAR> prevBuffer(size, 0);
  195.  
  196. bool firstRead = true;
  197.  
  198. while (isRunning) {
  199. if (ReadMemory(address, buffer.data(), size)) {
  200. if (firstRead || memcmp(buffer.data(), prevBuffer.data(), size) != 0) {
  201. std::cout << "\r" << std::setw(20) << " " << "\r";
  202. std::cout << "0x" << std::hex << address << ": ";
  203.  
  204. for (SIZE_T i = 0; i < size; i++) {
  205. std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(buffer[i]) << " ";
  206. }
  207.  
  208. // Also show as decimal for small values
  209. if (size <= 8) {
  210. std::cout << "| ";
  211. if (size == 4) {
  212. DWORD value = *reinterpret_cast<DWORD*>(buffer.data());
  213. std::cout << std::dec << value;
  214. } else if (size == 8) {
  215. ULONG64 value = *reinterpret_cast<ULONG64*>(buffer.data());
  216. std::cout << std::dec << value;
  217. }
  218. }
  219.  
  220. std::cout << std::endl;
  221. memcpy(prevBuffer.data(), buffer.data(), size);
  222. firstRead = false;
  223. }
  224. }
  225.  
  226. std::this_thread::sleep_for(std::chrono::milliseconds(interval));
  227. }
  228. }
  229.  
  230. void DisplayMenu() {
  231. std::cout << "Available commands:\n";
  232. std::cout << " help - Display this menu\n";
  233. std::cout << " process <pid> - Set target process ID\n";
  234. std::cout << " base - Get process base address\n";
  235. std::cout << " module <name> - Get module base address\n";
  236. std::cout << " read <addr> <size> - Read memory at address\n";
  237. std::cout << " write <addr> <data> - Write data to address (hex format)\n";
  238. std::cout << " monitor <addr> <size> [interval] - Monitor memory address\n";
  239. std::cout << " pattern <size> <pattern> - Create pattern for buffer overflow\n";
  240. std::cout << " scan <type> <value> - Scan for value in process memory\n";
  241. std::cout << " offset <name> <addr> - Save an offset with a name\n";
  242. std::cout << " offsets - List all saved offsets\n";
  243. std::cout << " calc <expression> - Calculate an expression with offsets\n";
  244. std::cout << " clear - Clear the screen\n";
  245. std::cout << " exit - Exit the program\n";
  246. }
  247.  
  248. void ProcessCommand(const std::string& command) {
  249. std::vector<std::string> args = SplitString(command, ' ');
  250.  
  251. if (args.empty()) {
  252. return;
  253. }
  254.  
  255. std::string cmd = ToLowerCase(args[0]);
  256.  
  257. if (cmd == "help") {
  258. DisplayMenu();
  259. }
  260. else if (cmd == "process" && args.size() > 1) {
  261. try {
  262. targetProcessId = std::stoul(args[1]);
  263. std::cout << "Set target process ID to: " << targetProcessId << std::endl;
  264.  
  265. // Automatically get process base address
  266. processBaseAddress = GetProcessBaseAddress(targetProcessId);
  267. if (processBaseAddress) {
  268. std::cout << "Process base address: 0x" << std::hex << processBaseAddress << std::dec << std::endl;
  269. }
  270. }
  271. catch (const std::exception&) {
  272. std::cout << "Invalid process ID\n";
  273. }
  274. }
  275. else if (cmd == "base") {
  276. if (targetProcessId == 0) {
  277. std::cout << "Please select a process first\n";
  278. return;
  279. }
  280.  
  281. processBaseAddress = GetProcessBaseAddress(targetProcessId);
  282. if (processBaseAddress) {
  283. std::cout << "Process base address: 0x" << std::hex << processBaseAddress << std::dec << std::endl;
  284. }
  285. }
  286. else if (cmd == "module" && args.size() > 1) {
  287. if (targetProcessId == 0) {
  288. std::cout << "Please select a process first\n";
  289. return;
  290. }
  291.  
  292. std::wstring moduleName(args[1].begin(), args[1].end());
  293. ULONG64 moduleBase = GetModuleBaseAddress(targetProcessId, moduleName.c_str());
  294.  
  295. if (moduleBase) {
  296. std::cout << "Module base address: 0x" << std::hex << moduleBase << std::dec << std::endl;
  297. // Save this in the offset cache as well
  298. offsetCache[args[1]] = moduleBase;
  299. }
  300. }
  301. else if (cmd == "read" && args.size() > 2) {
  302. try {
  303. ULONG64 address = ParseHexAddress(args[1]);
  304. SIZE_T size = std::stoul(args[2]);
  305.  
  306. if (size > 1024) {
  307. std::cout << "Size too large. Maximum is 1024 bytes.\n";
  308. return;
  309. }
  310.  
  311. std::vector<UCHAR> buffer(size, 0);
  312.  
  313. if (ReadMemory(address, buffer.data(), size)) {
  314. PrintMemory(buffer.data(), size, address);
  315. }
  316. }
  317. catch (const std::exception&) {
  318. std::cout << "Invalid parameters\n";
  319. }
  320. }
  321. else if (cmd == "write" && args.size() > 2) {
  322. try {
  323. ULONG64 address = ParseHexAddress(args[1]);
  324. std::string hexData = args[2];
  325.  
  326. // Remove 0x prefix if present
  327. if (hexData.substr(0, 2) == "0x") {
  328. hexData = hexData.substr(2);
  329. }
  330.  
  331. // Convert hex string to bytes
  332. if (hexData.length() % 2 != 0) {
  333. std::cout << "Hex data must have an even number of characters\n";
  334. return;
  335. }
  336.  
  337. std::vector<UCHAR> buffer;
  338. for (size_t i = 0; i < hexData.length(); i += 2) {
  339. std::string byteStr = hexData.substr(i, 2);
  340. UCHAR byte = static_cast<UCHAR>(std::stoul(byteStr, nullptr, 16));
  341. buffer.push_back(byte);
  342. }
  343.  
  344. if (WriteMemory(address, buffer.data(), buffer.size())) {
  345. std::cout << "Successfully wrote " << buffer.size() << " bytes to 0x"
  346. << std::hex << address << std::dec << std::endl;
  347. }
  348. }
  349. catch (const std::exception&) {
  350. std::cout << "Invalid parameters\n";
  351. }
  352. }
  353. else if (cmd == "monitor" && args.size() > 2) {
  354. try {
  355. ULONG64 address = ParseHexAddress(args[1]);
  356. SIZE_T size = std::stoul(args[2]);
  357. int interval = 1000; // Default interval in ms
  358.  
  359. if (args.size() > 3) {
  360. interval = std::stoi(args[3]);
  361. }
  362.  
  363. if (size > 64) {
  364. std::cout << "Size too large for monitoring. Maximum is 64 bytes.\n";
  365. return;
  366. }
  367.  
  368. MonitorValue(address, size, interval);
  369. }
  370. catch (const std::exception&) {
  371. std::cout << "Invalid parameters\n";
  372. }
  373. }
  374. else if (cmd == "pattern" && args.size() > 2) {
  375. try {
  376. SIZE_T size = std::stoul(args[1]);
  377. std::string pattern = args[2];
  378.  
  379. if (size > 1024) {
  380. std::cout << "Size too large. Maximum is 1024 bytes.\n";
  381. return;
  382. }
  383.  
  384. std::vector<UCHAR> buffer(size);
  385.  
  386. // Fill the buffer with the repeating pattern
  387. for (SIZE_T i = 0; i < size; i++) {
  388. buffer[i] = pattern[i % pattern.length()];
  389. }
  390.  
  391. std::cout << "Generated pattern (" << size << " bytes):\n";
  392. PrintMemory(buffer.data(), size, 0);
  393.  
  394. std::cout << "Would you like to write this pattern to a specific address? (y/n): ";
  395. std::string response;
  396. std::getline(std::cin, response);
  397.  
  398. if (response == "y" || response == "Y") {
  399. std::cout << "Enter address: ";
  400. std::string addrStr;
  401. std::getline(std::cin, addrStr);
  402.  
  403. try {
  404. ULONG64 address = ParseHexAddress(addrStr);
  405.  
  406. if (WriteMemory(address, buffer.data(), buffer.size())) {
  407. std::cout << "Successfully wrote pattern to 0x"
  408. << std::hex << address << std::dec << std::endl;
  409. }
  410. }
  411. catch (const std::exception&) {
  412. std::cout << "Invalid address\n";
  413. }
  414. }
  415. }
  416. catch (const std::exception&) {
  417. std::cout << "Invalid parameters\n";
  418. }
  419. }
  420. else if (cmd == "scan" && args.size() > 2) {
  421. ScanForValue(args[1], args[2]);
  422. }
  423. else if (cmd == "offset" && args.size() > 2) {
  424. try {
  425. std::string name = args[1];
  426. ULONG64 address = ParseHexAddress(args[2]);
  427.  
  428. offsetCache[name] = address;
  429. std::cout << "Saved offset '" << name << "' = 0x" << std::hex << address << std::dec << std::endl;
  430. }
  431. catch (const std::exception&) {
  432. std::cout << "Invalid parameters\n";
  433. }
  434. }
  435. else if (cmd == "offsets") {
  436. if (offsetCache.empty()) {
  437. std::cout << "No offsets saved\n";
  438. return;
  439. }
  440.  
  441. std::cout << "Saved offsets:\n";
  442. for (const auto& [name, address] : offsetCache) {
  443. std::cout << " " << std::left << std::setw(20) << name
  444. << " = 0x" << std::hex << address << std::dec << std::endl;
  445. }
  446. }
  447. else if (cmd == "calc" && args.size() > 1) {
  448. // Extract the expression from the rest of the command
  449. std::string expression;
  450. for (size_t i = 1; i < args.size(); i++) {
  451. expression += args[i];
  452. }
  453.  
  454. // Simple expression calculator that can handle addition and subtraction
  455. // of offsets and hex values
  456. try {
  457. std::vector<std::string> tokens;
  458. std::string currentToken;
  459. char lastOp = '+';
  460. ULONG64 result = 0;
  461.  
  462. // Tokenize the expression
  463. for (size_t i = 0; i < expression.length(); i++) {
  464. if (expression[i] == '+' || expression[i] == '-') {
  465. if (!currentToken.empty()) {
  466. tokens.push_back(currentToken);
  467. tokens.push_back(std::string(1, expression[i]));
  468. currentToken.clear();
  469. }
  470. }
  471. else {
  472. currentToken += expression[i];
  473. }
  474. }
  475.  
  476. if (!currentToken.empty()) {
  477. tokens.push_back(currentToken);
  478. }
  479.  
  480. // Evaluate the expression
  481. for (size_t i = 0; i < tokens.size(); i++) {
  482. if (tokens[i] == "+" || tokens[i] == "-") {
  483. lastOp = tokens[i][0];
  484. continue;
  485. }
  486.  
  487. ULONG64 value;
  488. if (offsetCache.find(tokens[i]) != offsetCache.end()) {
  489. value = offsetCache[tokens[i]];
  490. }
  491. else {
  492. value = ParseHexAddress(tokens[i]);
  493. }
  494.  
  495. if (lastOp == '+') {
  496. result += value;
  497. }
  498. else if (lastOp == '-') {
  499. result -= value;
  500. }
  501. }
  502.  
  503. std::cout << "Result: 0x" << std::hex << result << std::dec << std::endl;
  504. }
  505. catch (const std::exception&) {
  506. std::cout << "Invalid expression\n";
  507. }
  508. }
  509. else if (cmd == "clear") {
  510. system("cls");
  511. }
  512. else if (cmd == "exit") {
  513. isRunning = false;
  514. std::cout << "Exiting...\n";
  515. }
  516. else {
  517. std::cout << "Unknown command. Type 'help' for a list of commands.\n";
  518. }
  519. }
  520.  
  521. std::vector<std::string> SplitString(const std::string& input, char delimiter) {
  522. std::vector<std::string> tokens;
  523. std::string token;
  524. std::istringstream tokenStream(input);
  525.  
  526. while (std::getline(tokenStream, token, delimiter)) {
  527. if (!token.empty()) {
  528. tokens.push_back(token);
  529. }
  530. }
  531.  
  532. return tokens;
  533. }
  534.  
  535. std::string ToLowerCase(const std::string& input) {
  536. std::string result = input;
  537. std::transform(result.begin(), result.end(), result.begin(),
  538. [](unsigned char c) { return std::tolower(c); });
  539. return result;
  540. }
  541.  
  542. ULONG64 ParseHexAddress(const std::string& hexString) {
  543. std::string cleanHex = hexString;
  544.  
  545. // Remove 0x prefix if present
  546. if (cleanHex.substr(0, 2) == "0x") {
  547. cleanHex = cleanHex.substr(2);
  548. }
  549.  
  550. // Check if it's a known offset
  551. if (offsetCache.find(hexString) != offsetCache.end()) {
  552. return offsetCache[hexString];
  553. }
  554.  
  555. // Calculate base + offset if in format "base+offset"
  556. size_t plusPos = hexString.find('+');
  557. if (plusPos != std::string::npos) {
  558. std::string baseName = hexString.substr(0, plusPos);
  559. std::string offsetStr = hexString.substr(plusPos + 1);
  560.  
  561. if (offsetCache.find(baseName) != offsetCache.end()) {
  562. ULONG64 baseAddr = offsetCache[baseName];
  563. ULONG64 offset = std::stoull(offsetStr, nullptr, 16);
  564. return baseAddr + offset;
  565. }
  566. }
  567.  
  568. // Parse as regular hex address
  569. return std::stoull(cleanHex, nullptr, 16);
  570. }
  571.  
  572. void PrintMemory(UCHAR* buffer, SIZE_T size, ULONG64 address) {
  573. const SIZE_T bytesPerLine = 16;
  574.  
  575. for (SIZE_T offset = 0; offset < size; offset += bytesPerLine) {
  576. // Print address
  577. std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << (address + offset) << ": ";
  578.  
  579. // Print hex values
  580. for (SIZE_T i = 0; i < bytesPerLine; i++) {
  581. if (offset + i < size) {
  582. std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(buffer[offset + i]) << " ";
  583. }
  584. else {
  585. std::cout << " ";
  586. }
  587.  
  588. if (i == 7) {
  589. std::cout << " ";
  590. }
  591. }
  592.  
  593. // Print ASCII representation
  594. std::cout << " | ";
  595. for (SIZE_T i = 0; i < bytesPerLine; i++) {
  596. if (offset + i < size) {
  597. char c = buffer[offset + i];
  598. if (c >= 32 && c <= 126) {
  599. std::cout << c;
  600. }
  601. else {
  602. std::cout << ".";
  603. }
  604. }
  605. else {
  606. std::cout << " ";
  607. }
  608. }
  609.  
  610. std::cout << std::endl;
  611. }
  612.  
  613. // Print as different data types for small sizes
  614. if (size <= 8) {
  615. std::cout << "\nAs values: ";
  616. if (size >= 1) std::cout << "INT8: " << static_cast<int>(buffer[0]) << " ";
  617. if (size >= 2) std::cout << "INT16: " << *reinterpret_cast<short*>(buffer) << " ";
  618. if (size >= 4) std::cout << "INT32: " << *reinterpret_cast<int*>(buffer) << " ";
  619. if (size >= 4) std::cout << "FLOAT: " << *reinterpret_cast<float*>(buffer) << " ";
  620. if (size >= 8) std::cout << "INT64: " << *reinterpret_cast<INT64*>(buffer) << " ";
  621. if (size >= 8) std::cout << "DOUBLE: " << *reinterpret_cast<double*>(buffer) << " ";
  622. std::cout << std::endl;
  623. }
  624. }
  625.  
  626. void ScanForValue(const std::string& valueType, const std::string& valueStr) {
  627. if (targetProcessId == 0) {
  628. std::cout << "Please select a process first\n";
  629. return;
  630. }
  631.  
  632. std::cout << "Memory scanning is not implemented yet. This would require additional driver support.\n";
  633. std::cout << "Would typically scan for " << valueType << " with value " << valueStr << ".\n";
  634.  
  635. // In a real implementation, this would use the driver to scan process memory
  636. // The basic implementation would:
  637. // 1. Enumerate all memory regions
  638. // 2. Read memory in chunks
  639. // 3. Compare against the target value
  640. // 4. Report matches
  641. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement