{
	"id": "1d295858-e840-4b0f-9e4e-9395cf1c0f7c",
	"created_at": "2026-04-06T00:14:37.686046Z",
	"updated_at": "2026-04-10T13:11:29.34383Z",
	"deleted_at": null,
	"sha1_hash": "857a5eda4d401e11cd51d7b8357e9f7c4a11d43a",
	"title": "The ‘Madi’ infostealers - a detailed analysis",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 475852,
	"plain_text": "The ‘Madi’ infostealers - a detailed analysis\r\nBy Nicolas Brulez\r\nPublished: 2012-07-27 · Archived: 2026-04-05 17:55:21 UTC\r\nOn 17 July, we published a blog about Madi and the ongoing campaign used to infiltrate computer systems\r\nthroughout the Middle East that has targeted users in Iran, Israel, Afghanistan and other individuals scattered\r\nacross the globe. Here is the follow up with a detailed analysis of the infostealer used in the campaign.\r\nInstallation\r\nThe infostealer is installed by one of the various downloaders used in the attacks, which can be separated into two\r\ncategories:\r\nDownloaders using the social engineering techniques described in our first blog post (displaying pictures,\r\nmovies, documents etc.) to trick the user\r\nDownloaders that simply download and install the infostealer\r\nBoth types of downloaders copy themselves as “UpdateOffice.exe” into the “Printhood” directory, e.g.:\r\n“C:Documents and Settings%USER%PrintHoodUpdateOffice.exe” where they start executing.\r\nBoth the infostealer and downloaders create fake files with random names in their respective folders. The\r\ndownloaders also drop some files which assist the malware (see our first blog for details).\r\nOnly one file will be used by the infostealer: nam.dll. This file is created by the downloader in the “Templates”\r\ndirectory (e.g.: “C:Documents and Settings%USER%Templatesnam.dll”) and contains a BOT prefix/build that\r\nwill be used by the infostealer when connecting to the command and control server (C\u0026C). In order to download\r\nand install the infostealer, the downloaders connect to the C\u0026C server to request an HTM page.\r\nOlder variants use http://[C\u0026C address]/ASLK/khaki/Abi/UUUU.htm, whereas more recent ones use\r\n“http://[C\u0026C address]/ASLK/asgari/mah/UeUeUeUe.htm”.\r\nThe HTM page is a copy of Google index, with a double BASE64 encoded executable embedded in the page:\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 1 of 23\n\nThe keyword “tamamshodfile” at the bottom will be explained in the ‘Infostealer analysis’ section below.\r\nThe downloaders simply parse the HTM file, and decode the Base64 payload twice and save the resulting PE file\r\nas “iexplore.exe” in the “Templates” directory. Once downloaded, the infostealer is executed.\r\nInfostealer analysis: Iexplore.exe\r\nAll the versions of the infostealer have an Internet Explorer icon, and were written in Delphi.\r\nThe version used in this article, which appears to have been compiled on 10 June 2012, is packed using UPX 3.08.\r\nThe file is rather big: 415 KB packed, and 1.14 MB once unpacked.\r\nOne peculiarity of the infostealer used in the Madi campaign is the heavy use of Delphi Timers. There are 52 of\r\nthem as you can see on the screenshot below:\r\n.\r\nNumerous bugs were discovered during the analysis of the infostealer. Some of them won’t be discussed here as\r\nwe don’t want to help the authors improve their malware.\r\nTForm4.FormCreate:\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 2 of 23\n\nUpon execution, the first activity of interest performed by the infostealer happens inside TForm4.FormCreate.\r\nIt starts with the setup of a keylogger. In order to do so, Madi infostealer uses the Windows function\r\n“SetWindowsHookEx” with the “WH_KEYBOARD_LL” Id_Hook.\r\nOnce the keylogger has been installed, the infostealer reads the “nam.dll” file (dropped by the downloader) to get\r\nthe BOT prefix and concatenates it with the computer name. Hereafter this will be referred to as “BOTID_TMP”.\r\nThe final BOTID contains some numbers derived from the “C:” Volume Serial Number, as we will see later on.\r\nThe following timers are then disabled in this specific order:\r\nTimer1, Timer16, Timer18, Timer17, Timer20, Timer19, Timer24, Timer8, Timer30, Timer31, Timer33, Timer34,\r\nTimer36, Timer37, Timer38, Timer39, Timer40, Timer41, Timer44, Timer45, Timer46, Timer48, Timer49,\r\nTimer50.\r\nThe malware uses a lot of external files to receive commands, which is another indicator of poor programming\r\nskills. Those files are used to inform the malware about the infection status. In order to avoid confusion, hereafter,\r\nwhen referring to a file, it is in the malware directory (“Templates” directory), unless stated otherwise.\r\nThe infostealer looks for the following files:\r\n“fsdiskget.dll”: If found, it enables Timer 23 – otherwise, disables it.\r\n“nrbindek.dll” : If found, it enables Timer 28 – otherwise, disables it.\r\n“specialfile.dll”: If found, it deletes it.\r\n“filesend.xls”: Doesn’t actually look for it; just tries to delete it.\r\n“begirnagir.htp” : If NOT found, it disables Timer3\r\n“filebind.xls”: If found, it enables Timer29 – otherwise, disables it.\r\nNext, Timer14 and Timer13 are both disabled.\r\nThe Trojan looks for “First.dll”, which is created the first time the malware is executed.\r\nIf already present, the code returns from TForm4.FormCreate. Otherwise, the following happens.\r\nIt creates first.dll with a hardcoded stream of bytes (not a real .dll, like the .dll mentioned above, as we will see\r\nlater on when we analyze the timers more closely).\r\nLike the downloaders, the infostealer also generates fake files with random names. Before returning from\r\nTForm4.FormCreate, 6 loops will be executed:\r\nXLS: 51 fake XLS files with random names (7 characters) are generated using a hardcoded stream of bytes.\r\nEXE: 51 fake EXE files with random names (6 characters) are generated using a hardcoded stream of bytes.\r\nDLL: 201 fake DLL files with random names (9 characters) are generated using a hardcoded stream of bytes.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 3 of 23\n\nTXT: 51 fake TXT files with random names (4 characters) are generated using a hardcoded stream of bytes.\r\nXML: 51 fake XML files with random names (8 characters) are generated using a hardcoded stream of bytes.\r\nHTM: 51 fake HTM files with random names (8 characters) are generated using a hardcoded stream of bytes.\r\nKeylogger analysis:\r\nAs mentioned before, the keylogger setup is done in the TForm4.FormCreate. It uses “SetWindowsHookEx” with\r\nthe “WH_KEYBOARD_LL” Id_hook to intercept keystrokes.\r\nThe hook function is rather rudimentary. For instance, it uses the GetAsyncKeyState, with the “VK_BACK” to\r\nfind out if the victim used backspace.\r\nFor each typed key, there is a handler to save which key was typed in the keylogger buffer “poki65_pik_log”:\r\nIt comes as no real surprise that the keylogger is very basic and makes no use of any advanced technologies.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 4 of 23\n\nThe malware uses 52 timers. Therefore, we will group them by actions, in order to make the overall analysis easier\r\nto follow.\r\nCommand and control: Protocol\r\nWe are now going to cover all the timers responsible for contacting the C\u0026C server and receiving commands to\r\nexecute on the infected machine, and all the various handlers used to execute actions according to those orders.\r\nNote: In many routines, Madi creates “.bat” files in order to ping the C\u0026C server to see if it is up or not and saves\r\nthe result in a special file. Each file has a different name. If these files are referenced, we will provide the timer\r\nnumber responsible for its creation.\r\nThe server manager looks like this:\r\nThe GUI was probably rushed, but it serves its purpose. It can be used to create specific tasks for victims. See\r\nTimer 12 to see how each command is handled by the infostealer.\r\nTimer 1: Check-in\r\nInterval: 25 seconds\r\nBefore receiving commands, the infostealer connects to the C\u0026C to a special page. I call it the check-in routine.\r\nHere is the description:\r\nTimer 1 gets the ApplicationName and concatenates it with “.pkklm” (See Timer 15 description for details on how\r\nthis file is created). It tries to open that file, looking for the “Reply From” string (when the IP responds to a ping).\r\nIf it’s not found, it disables Timer 1 and returns.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 5 of 23\n\nIf present, the last part of the BOTID is generated using the “C:” Volume Serial Number.\r\nBasically, the API function GetVolumeInformationW is called to get the Volume Serial Number, which is then\r\nconcatenated to the BOTID_TMP generated in the TForm4.FormCreate. Now that the final BOTID has been\r\ngenerated, the final URL that is visited is generated as follows:\r\nBOTID|COMPUTERNAME|VolumeSerialNumber/dastor/file.htm\r\ne.g.: abaanu5|MYCOMPUTER-8712422C|6D8704FE/dastor/file.htm\r\nThe final URL is visited using Internet Explorer (IE) instrumentation.\r\n(e.g.: http://C\u0026C/abaanu5MYCOMPUTER-8712422C6C7704EF/dastor/file.htm)\r\nOnce visited, it enables Timer 18, disables Timer 1 and returns.\r\nThis is the checking-in process, which can tell the attackers when a victim computer is ready to receive\r\ncommands.\r\nOnce the attackers have decided to send commands to the infected computer, a “das.htm” will be available in the\r\n“/dastor/” folder.\r\nTimer 16: Visit commands page\r\nInterval: 25 seconds\r\nTimer 1 gets the ApplicationName and concatenates it with “.pkxm” (ping results from Timer 11). It tries to open\r\nthat file, looking for the “Reply From” string (when the IP responds to a ping).\r\nIf it’s not found, it disables Timer 16 and returns.\r\nThe Final BOTID is computed (see Timer 1 description) to build the URL that is visited in order to receive\r\ncommands. Before visiting that URL, the “dast.xls” file is deleted (see Timer 17 below).\r\nThe URL is visited using IE instrumentation. Timer 17 is enabled, and Timer 16 disabled.\r\nTimer 17: Save the command page as “dast.xls”\r\nInterval: 20 seconds\r\nNote: During the execution of the Madi infostealer, many instances of IE are running.\r\nTimer 17 will go through all the different instances of instrumented IE, looking for pages with “dastor” in their\r\ntitle. Once found, the content of the page (without the title) is saved as “dast.xls”.\r\nIf nothing is found, it will go to next IE instance, and repeat the checks until no instances are left. If nothing is\r\nfound, a clean-up routine is launched.\r\nAt the end of the Timer 17, it looks for ” – dastor – Windows Internet Explorer” and different variants (Internet\r\nExplorer) and sends a “WM_Close” Message using the “PostMessageW” function in order to close the page.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 6 of 23\n\nAmong all those captions, it also looks for ” – 404 – File or directory not found” and variants of 404 pages, if the\r\npage wasn’t found.\r\nOnce the clean-up is completed, Timer 17 disables itself and returns.\r\nAt this point, we have a local file with the commands to execute on the infected machine.\r\nTimer 12: Command dispatcher\r\nThis timer is responsible for parsing the command file. In order to make the description a little easier to follow,\r\nhere is a sample command file:\r\nWhen executed, Timer 12 is disabled.\r\nThe infostealer Trojan then checks if the file “dast.xls” is present (created by Timer 17, see above).\r\nIf it’s not present, Timer 12 is re-enabled and returns.\r\nThe next stage of the process opens “dast.xls” which searches for commands to execute (see the command file\r\nabove). Lots of commands can be sent simultaneously, meaning Timer 12 will not stop parsing when one\r\ncommand is found. Here is the full logic of the parsing:\r\nPIK:\r\nIf the command file contains the word “pik”, it checks if the status of Timer 3 is enabled. (Timer 3 is a webmail,\r\nsocial network and IM screen capture routine.)\r\nIf not enabled, Timer 3 is enabled, and screen monitoring begins. Command parsing continues. If the “pik”\r\ncommand is not found, Timer3 is disabled.\r\nDESK:\r\nIf the command file contains the word “desk”, it checks if the status of Timer 13 is enabled. (Timer 13 is a screen\r\ncapture routine.)\r\nIf not enabled, Timer 13 is enabled, and screen monitoring begins. Command parsing continues. If the “desk”\r\ncommand is not found, Timer13 is disabled.\r\nSOUND:\r\nIf the command file contains the word “sound”, it checks if the status of Timer 14 is enabled. (Timer 14 is a sound\r\nrecording routine.)\r\nIf not enabled, Timer 14 is enabled, and sound recording begins. Command parsing continues. If the “sound”\r\ncommand is not found, Timer14 is disabled.\r\nIf the command file contains the word “newfi”, nothing happens. This is probably a leftover from older code.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 7 of 23\n\nUPDATE:\r\nIf the command file contains the word “update”, it checks to see if it also contains a version number, which must\r\nbe different from current version (“1.1.6” in the analyzed sample). If neither of those two conditions are valid, it\r\ngoes to the next command parsing. The checking routine is very simplistic and assumes that the version number\r\nwill be higher, not lower. It is therefore possible to downgrade the Trojan.\r\nIf the required update criteria are met, it will create “Update.dll”. (Update.dll is made from a hardcoded stream of\r\nbytes and isn’t a valid DLL.)\r\nThe Trojan now locates the “STARTUP” folder where a copy of the “UpdateOffice.exe” (Trojan downloader) is\r\nfound, and executes it using ShellExecute. (In the first part of the article, we explained how the downloader\r\ndownloads and installs the infostealer.)\r\nThe Trojan downloader is necessary in order for updates to occur. If the downloader has been deleted for some\r\nreason, the update won’t be performed.\r\nOnce executed, Timer 12 terminates its execution, as the infostealer executable (iexplore.exe) will be overwritten\r\nby the Trojan downloader with a newer version and executed.\r\nDELETE:\r\nIf the command file contains the word “delete”, it will create “delete.dll”, using exactly the same stream of bytes\r\nthat is used in “update.dll”.\r\nThe Trojan now locates the “STARTUP” folder where a copy of the “UpdateOffice.exe” downloader is located,\r\nand deletes it. Once deleted, it then proceeds to terminate itself.\r\nAt this point, upon the next reboot, the infection isn’t restarted.\r\nNote: The infostealer doesn’t restart by itself, allowing an automatic update every time the computer reboots.\r\nOn the other hand all the other downloader files (non-malicious) are still present in the /printhood/ folder. The full\r\nfolder of the infostealer is still present, as is the malware.\r\nBIND:\r\nIf neither “update” nor “delete” are found, Timer 12 checks if the command file contains the word “bind” and\r\ncreates “nrbindek.dll” using exactly the same stream of bytes that is used in “update.dll”.\r\nNothing else happens at this point. However, as we have seen in the Form creation, upon execution, the malware\r\nchecks whether “nrbindek.dll” is present.\r\nIf it is present, Timer 12 will enable Timer 28.\r\nIf “bind” isn’t found, the parsing continues with the next command.\r\nDISKGO:\r\nIf the command file contains the word “diskgo”, it will create “lbdiskgo.dll”, using exactly the same stream of\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 8 of 23\n\nbytes that is used in “update.dll”. Parsing continues with next command.\r\nNote: “lbdiskgo.dll” is checked by Timer 42 and Timer 43.\r\nDISKGET:\r\nIf the command file contains the word “diskget”, it will create “fskdiskget.dll”, using exactly the same stream of\r\nbytes that is used in “update.dll” and enable Timer 23.\r\nTimer 12 then checks whether “specialfile.dll” is present. If NOT, it will look for the file extensions included in\r\nthe command that was received. The attackers select from a list of 27 extensions that are provided by the C\u0026C\r\nserver, and which can be selected using a Remote Control Tool (see at the beginning of the Timer 12 description to\r\nview the extensions listed in the sample command file).\r\nEach file extension is separated by a special marker “$.$”.\r\nTimer 12 searches for the “$.$” marker. If it’s not present, the parsing stops there.\r\nIf the marker is present, it saves those extensions to the “specialfile.dll” and enables Timer 26.\r\nNote: Specialfile.dll is therefore used to tell the malware what file extensions to look for and Timer 26 will handle\r\ndiskget.\r\nAfterwards, or if specialfile.dll was already present, it will check whether the “logfi.dll”\r\nis present, and stop parsing commands if it is not.\r\nIf the file is present, it looks in the command buffer for the word “file” and exits the commands parsing if not\r\nfound.\r\nIf logfil.dll is present, it will search files on fixed hard drives and remote drives. The authors’ poor programming\r\nskills are quite noticeable in this part of the code.\r\nIt is also interesting to note that it will search for “MHTML” files, even if that option isn’t available in the Server\r\nControl tool, and that they made a duplicate entry in the hardcode list of files that need to be to located (htm is\r\npresent twice).\r\nFile types searched:\r\n*.*txt/*.*jpg/*.*doc/*.*pdf/*.*bmp/*.*docx/*.*mdb/*.*xls/*.*csv/*.*html/*.*avi/\r\n*.*mp3/*.*wave/*.*htm/*.*rar/*.*zip/*.*htm\r\n(again?!)/*.*gif/*.*7z/*.*jar/*.*JPEG/*.*mp4/*.*3gp/\r\n*.*dat/*.*MPEG/*.*SWF/*.*WMV/*.*xml/*.*MHTML/\r\nTotal of 29 extensions, with one duplicate. 27 extensions are present in the Server Control tool and one that is not\r\n(MHTML).\r\nIt saves the log file as “logfi.dll” for each hard drive and creates a backup as “logfi.dll.BMH”. It will overwrite the\r\nlogs for each iteration of the loop.\r\nIt only search files on remote and fixed drives, not on USB/external drives; that’s for the logging part.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 9 of 23\n\nOnce the Parsing is complete, Timer 12 re-enables itself and exits.\r\nMonitoring\r\nTimer 3: PIK handler – Webmail, social network and IM screen capture\r\nInterval: 60 seconds.\r\nTimer 3 creates a “begirnagir.htp” file.\r\nIt then checks whether the user has been surfing or using the following applications and takes a screen capture if\r\nfound:\r\ngmail, hotmail, yahoo! mail, google+, msn messenger, blogger, massenger (?), profile,icq, paltalk, yahoo!\r\nmessenger for the web, skype, facebook.\r\nThe screen captures are saved as a JPG using the following name convention: mm-dd-yyyy-hhnnss. The “Now”\r\nand “FormateDateTime” functions are used.\r\nTimer 13: DESK handler – Screen capture\r\nInterval: 3 minutes\r\nNote: The GUI used to control the bot says 2 minutes, but the code doesn’t lie.\r\nTimer 13 takes screen captures every 3 minutes. They are saved using the following name convention: mm-dd-yyyy-hhnnss. The “Now” and “FormateDateTime” functions are used.\r\nThe files are in JPG format.\r\nTimer 14: SOUND handler – Recording sound\r\nThis timer is responsible for starting the audio recording using the mci* functions from winmm.dll.\r\nThe following commands are used: “OPEN NEW TYPE WAVEAUDIO ALIAS mysound”, “SET mysound TIME\r\nFORMAT MS BITSPERSAMPLE 8 CHANNELS 1 SAMPLESPERSEC 8000 BYTESPERSEC 8000” and\r\nfinally “RECORD mysound”.\r\nOnce the commands are sent, Timer 30 is enabled, and Timer 14 returns.\r\nTimer 30: Started by Timer 14 (sound command handler)\r\nInterval: 60 seconds\r\nThis timer does anything apart from start Timer 31 when it is time to save the recoded audio.\r\nTimer 31: Started by Timer 30 (when it is time to save audio recordings)\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 10 of 23\n\nWhen sufficient time has passed since the start of audio recording, Timer 31 disables Timer 30, stops the recording\r\nby sending the following command: “STOP mysound”.\r\nTo save audio files, it sends the “SAVE mysound” command. The files are saved using the following name\r\nconvention: mm-dd-yyyy-hhnnss. The “Now” and “FormateDateTime” functions are used.\r\nThe final file is saved as .wav.BMH.\r\nTimer 31 is then disabled, and Timer 14 (Sound handler) is re-nabled for the next audio recording.\r\nTimer 32: Set up keylogger\r\nInterval: 60 seconds\r\nEven though the keylogger setup is performed when the application starts, in the FormCreate routine Timer 32\r\nsets up the keylogger every 60 seconds. The details of the keylogger have already been described earlier in this\r\ndocument.\r\nTimer 2: Creation of keylogger logs\r\nInterval: 10 seconds\r\nTimer 2 starts by getting the current user name (GetUserName API Function), and then checks if the “poki65.pik”\r\nfile is present. This file is the current ongoing keylogging file. If it’s not present, it looks for “solt.html”, which\r\nindicates whether the keylogger has created its first log yet.\r\nIf none of those files are present, it means it is the first time the keylogger has started logging.\r\nThe first log file is different from subsequent log files, as it contains more information. The Madi keylogger files\r\nuse HTML tags and colors to make them easier to read.\r\nFor the first log, it executes “cmd.exe /c ipconfig /allcompartments \u003e ipconfig.txt”\r\nIt waits 5 seconds and appends the content of “ipconfig.txt” to the HTML content that is created.\r\nThe computer name as well as the current user name is appended to the log, followed by the list of available\r\ndrives: Floppy Drive, Fixed Drive, Network Drive, CD-Rom Drive and RAM Disk.\r\nFinally, a full list of installed software, including security patches, is appended to the log file,\r\nas can be seen on the screenshot below:\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 11 of 23\n\nOnce this part is completed, it creates a file called “solt.htm” containing the word “wertik”.\r\nIt will continue formatting the poki65 log file. At the very beginning you can see the “Content-Language” set to\r\n“fa”, which is Persian.\r\nThis is how the keylogger logs are generated.\r\nTimer 4: Insert time stamps and tags to display screen captures into keylogger logs.\r\nInterval: 1 millisecond\r\nTimer 4 is responsible for inserting IMG tags inside the keylogger log. It is also responsible for adding the time\r\nstamp taken from the C\u0026C server (see Miscellaneous section, Timer 7 and 8).\r\nTimer 6: Backup keylogger log for exfiltration\r\nTimer 6 searches for the poki65.pik file – the current log session. If not found, it returns.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 12 of 23\n\nIt then looks for the size of the log file. If it is lower than 15 KB, it will return.\r\nOnly log files bigger than 15 KB are exfiltrated. If the size criteria is met, they are copied using the following\r\nname convention: mm-dd-yyyy-hhnnss.HTM. Timer 6 then deletes “poki65.pik” and returns.\r\nNote: A new log will be created by Timer 2 (solt.html tells the keylogger not to list drives, installed software etc.\r\nagain).\r\nDATA STEALING\r\nData stealing is handled by several timers. Each type of stolen data is stored in a special folder in the server. Files\r\nexfiltrated to the C\u0026C servers are Base64 encoded.\r\nBIND:\r\nTimer 28: Started during Form Creation (related to the BIND command)\r\nNote: When the infostealer starts, Timer 28 is enabled if the file “nrbindek.dll” is present (created by the BIND\r\ncommand).\r\nTimer 28 searches for “*.*exe” files on all fixed hard drives. For each *EXE* file found that doesn’t belong to the\r\n“Windows”, “Program Files” or “Program Files (x86)” folders, an entry (full path to *EXE* file) is added to the\r\nfile filebind.xls.\r\nOnce the hard drives have been scanned, Timer28 returns.\r\nFilebind.xls therefore contains all the executables on the fixed hard drives, except from those in Windows and\r\nProgram Files.\r\nTimer 29: Started during Form Creation (related to the BIND command)\r\nNote: The code of this timer is some of the worst that is used in the infostealer. The programming, obfuscated with\r\nDelphi, is very bad.\r\nTimer 28 generates a list of *EXE* files that don’t belong to the “Windows”, “Program Files” or “Program Files\r\n(x86)” folders. For each entry of that file, Timer 29 will make a backup of the executables. The *.bind* extension\r\nis appended to their original name.\r\nMany files are used to monitor the exfiltration status of the executables.\r\nHowever, Timer 29 doesn’t actually seem to exfiltrate anything, probably because of bugs.\r\nTimer 9: Check for files ready to be uploaded\r\nInterval: 5 seconds\r\nTimer 9 is disabled. If either Timer 19 or Timer 20 is enabled, it means there is already an active exfiltrating task.\r\nTimer 9 is enabled and it returns.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 13 of 23\n\nOtherwise, Timer 9 searches for files *.*KILOP as well as *.htm.BMH* files in the malware directory. KILOP\r\nfiles are Base64 encoded versions of files to exfiltrate. If no file is found, Timer 9 is enabled and returned.\r\nIf files are present, they are ready to be exfiltrated, and Timer 19 is enabled.\r\nBefore returning, Timer 9 is enabled.\r\nTimer 19: Check if IE instrumentation has been used to visit the upload page.\r\nInterval: 25 seconds\r\nTimer 19 searches for a specific page title:\r\nIf the page title “new title hastam – Microsoft Internet Explorer” is found, Timer 19 returns.\r\n“OKshodiha – Windows Internet Explorer” means a file is ready to be uploaded – Timer 20 is enabled and returns.\r\nIf none of those captions are found, Timer 19 starts IE_Instrumentation and visits the Sendfilejj.html page, enables\r\nTimer 20, then returns.\r\nTimer 20: File upload\r\nTimer 20 searches for *.*KILOP files, computes the BOTID (see Timer 1 for details), and fills the POST\r\nparameters. The “S0”, “S1” and “S2” forms present in the Sendfilejj.html are “filled” and the file is uploaded\r\nusing IE Instrumentation.\r\nT3, is the BOTID+Folder used for uploading (see below)\r\nT2 is the file name\r\nT1 is the Base64 encoded content of the file.\r\nTo compute T3, the following folder is appended to the BOTID (each victim has a root folder named after the\r\nBOTID on the C\u0026C).\r\n“/Pi/” for .jpg.BMH – Screen Captures\r\n“Te/ for .htm.BMH – Keylogger logs\r\n“/So/ for .wav.BMH – Audio Recordings\r\n“/Fi/” for important.file.BMH\r\n/Fi/CoolDisk/” for .fildik.BMH (data stolen from removable drives)\r\nFiles are sent via the Sendfilejj.html page hosted on the C\u0026C, which is a wrapper for the “sik.php” script used to\r\nreceive exfiltrated data.\r\nTimer 5: Base64 encoder for exfiltrated data\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 14 of 23\n\nInterval: 1 millisecond\r\nWhen triggered, it disables Timer 5, searches for *.*BMH files (files that will be exfiltrated once Base64 encoded)\r\nin the malware folder. When one file is found, it checks if the file is indeed on the disk and accessible. It Base64\r\nencodes it and saves it as nameoffile.BMH.KILOP. The non encoded version (BMH) is deleted, Timer 5 is re-enabled and it returns. Files are handled one by one, but the timer interval is very small, therefore it’s almost\r\ninstantaneous.\r\nNote: The resulting encoded files are those handled by Timer 20 described above. The process occurs as follows:\r\nTimer 9 enables Timer 19, which enables Timer 20 to upload files generated by Timer 5.\r\nTimer 21: Filesend.xls parser\r\nFilesend.xls has a list of files to exfiltrate.\r\nUpon execution, Timer 21 is disabled. If “filesend.xls” is present, it is opened and read.\r\nAll the files to be exfiltrated are separated by the “*” character as in the example below:\r\n*C:Documents and Settings%USER%\r\nDesktoptoolsstealme.txt**C:Documents and Settings%USER%\r\nDesktoptoolsstealme2.txt*\r\nTimer 21 parses each entry, and will check whether the file exists. If it does, a copy of the file will be made in the\r\nmalware directory with a .file.BMH extension. (In my example, we have: “stealme.txt.file.BMH”.)\r\nTimer 10: Tracking what was uploaded and cleaning IE instrumentation pages\r\nWhen a file has been uploaded using Timer 20, a POST is made to the sik.php file, a page is returned containing\r\nthe name of the uploaded file, as well as the hardcoded string “Save Shode” as you can see on the screen capture\r\nbelow:\r\nTimer 10 is responsible for keeping track of some of the uploaded files. Exfiltrated files are added to the\r\n“rafteha.zip”, which lists the files that have already been handled. The last file path to be handled is saved to the\r\n“fileomade.xls” file.\r\nTimer 15: Check for “filesend.xls”\r\nTimer 15 is disabled upon execution and “filesend.xls” is sought. If present, Timer 15 is enabled and it returns.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 15 of 23\n\nIf not, it checks whether Timer 1 is enabled. If Timer 1 is enabled, it enables Timer 15 and returns.\r\nIf Timer 1 isn’t enabled, Timer 15 checks the status of Timer 18. If it is enabled, Timer 15 re-enables itself and\r\nreturns.\r\nIf “filesend.xls” isn’t present and both Timer 1 and Timer 18 are disabled, it creates a “pangtkp.bat” file, which\r\ncontain “ping C\u0026C_IP \u003eC:DOCUME~1%USER%TEMPLA~1iexplore.exe.pkklm”.\r\nThat bat is executed, and both Timer 1 and 5 are enabled before returning.\r\nThere are other timers that are in some way or other related to exfiltration and data stealing, but they are all fairly\r\nsimilar. There is a lot of redundancy in the malware.\r\nTimer 23: List all removable drives on the machine\r\nTimer 23 lists all the removable drives on the machine, enables Timer 24, Timer 23 disables itself and returns.\r\nTimer 24: Search and copy files from removable drives\r\nTimer 24 receives the list of removable drives computed by Timer 23, and searches all the files on the devices.\r\nStolen files will be copied to the malware directory with fildik.BMH extensions, which will later be encoded as\r\nfildik.BMH.KILOP (Base64) and exfiltrated.\r\nThe list of processed files are stored inside raftehacool.zip.\r\nMiscellaneous\r\nThe infostealer contains 52 timers. Some of them do not perform any important tasks. The authors decided to ping\r\nthe C\u0026C server and save the results under specific file names. Those files are checked and parsed in order to find\r\nout if the C\u0026C is up and if certain actions can be taken. This is pretty amateurish programming.\r\nTimer 44: simple ping via pangtipo.bat\r\nTimer 44 is disabled upon execution. Timer 44 checks whether Timer 45 is enabled and returns if it is. (Timer 44\r\nis enabled prior to returning.)\r\nIf Timer 45 is disabled, a “pangtipo.bat” file is created, which contains “ping C\u0026C_IP\r\n\u003eC:DOCUME~1%USER%TEMPLA~1iexplore.exe.pkxml”.\r\nThe bat file is executed, Timer 44 is enabled and Timer 44 returns.\r\nTimer 11: Simple ping from pangtip.bat\r\nTimer 11 is disabled upon execution.If Timer 16 is already enabled, Timer 11 re-enables itself and returns. If\r\nTimer 17 is already enabled, Timer 11 re-enables itself and returns.\r\nIf none of the timers are enabled, it creates the “pangtip.bat” file, which contains “ping C\u0026C_IP\r\n\u003eC:DOCUME~1%USER%TEMPLA~1iexplore.exe.pkxm” and executes it via ShellExecute.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 16 of 23\n\nTimer 16 is enabled and returns.\r\nNote: Timers 1, 7, 11, 15, 44 and 48 generate these batch files under different names and the results are saved\r\nunder different names too.\r\nTimer 7: Was “timeip.php” visited?\r\nTimer 7 is disabled upon execution. Timer 7 checks whether the timeip.php page was visited. If not, it visits the\r\npage using IE instrumentation, Timer 7 disables itself and enables Timer 8 (see description below).\r\nIt creates the “pangip.bat” file, which contain “ping C\u0026C_IP”. Results are saved as “iexplore.exe.pkam”.\r\nNote: the file name used to save the output of the ping commands is based on the infostealer executable name,\r\nwhich is “iexplore.exe”. If the executable is renamed, the log files will have different names.\r\nTimer 8: Parse the results of the timeip.php visit\r\nThe timeip.php script returns the current time and the IP address of the victim. The results of the visit (done with\r\nIE instrumentation in Timer 7) are saved into a buffer which is used during the keylogger log creation (see Timer 4\r\ndescription).\r\nTimer 22: Ensure there is a backup copy of UpdateOffice (downloader)\r\nNote: The downloader is the only malware that starts after Windows boots. It’s therefore important to ensure\r\nvarious backup copies are made.\r\nTimer 22 checks if “UpdateOffice.exe” is present in the infostealer directory (templates). It shouldn’t be, as it is\r\nonly present in the printhood directory. (See Downloader description at the beginning of the article.)\r\nSince it is not present, it calls a subroutine to get the path to the “Printhood” directory (GetSpecialFolderLocation\r\nwith CSIDL_PRINTHOOD parameter). While concatenating the “UpdateOffice.exe” and the “Printhood” folder,\r\nthe “” character is missing, and therefore, the routine is bugged. The returned string is: “C:Documents and\r\nSettings%USER%PrintHoodUpdateOffice.exe” instead\r\nof “C:Documents and Settings%USER%PrintHoodUpdateOffice.exe”.\r\nIt then copies (or at least tries to, as the path is wrong) “C:Documents and\r\nSettings%USER%PrintHoodUpdateOffice.exe” as “srAntiq.dll” in the Templates folder.\r\nIf “OfficeUpdate.exe” isn’t present in the “printhood”, a copy is made from “srAntiq.dll”.\r\nIt retrieves the path to the Startup Folder using the CSIDL_STARTUP: “C:Documents and Settings%USER%Start\r\nMenuProgramsStartup”.\r\nTimer 22 checks whether “OfficeUpdate.exe” is present in that folder; if not, it will make a copy of srAntiq.dll to\r\nthe Startup folder and returns from Timer 22.\r\nTimer 25: Check for “fsdiskget.dll”\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 17 of 23\n\nTimer 25 checks if “fsdiskget.dll” is present in the malware directory; if not, it returns.\r\nIf the file is present, it enables Timer 23 (see the Data Stealing section for a description).\r\nTimer 42: lbdiskgo.dll, soltanik.dll and res.exe checking\r\nTimer 42 checks whether a flag (set by Timer 34 and cleared by Timer 33) is set to 0 and if lbdiskgo.dll,\r\nsoltanik.exe and res.exe are present. If they are, it enables Timer 33; otherwise, it returns.\r\nTimer 43: lbdiskgo.dll / ladine.dll / res.exe checking\r\nTimer 43 returns directly if neither “lbdiskgo.dll” or “ladine.dll” are present. If res.exe is present, it enables Timer\r\n44 and Timer 48; otherwise, it returns.\r\nTimer 45: Visit the ReReReRe.htm page\r\nTimer 45 deletes pangtipo.bat, reads iexplore.pkxml to make sure the C\u0026C replied. (Timer 1 and Timer 16\r\nprovides some more details on the use of such .bat files.)\r\nUses FindWindow to check whether IE Instrumentation has been used to visit the special ReReReRe.html page,\r\nwhich contains the following title: “r!r!r!r!”.\r\nIt looks for different variants such as “r!r!r!r! – Windows Internet Explorer” or “r!r!r!r! – Microsoft Internet\r\nExplorer”.\r\nIf one of them is found, it means the page was visited using IE instrumentation. It disables Timer 45 and returns.\r\nIf none of them are found, Timer 45 will visit the URL http://C\u0026CIP/ASLK//asgari/mah/ReReReRe.htm, enable\r\nTimer 46 (see below), disable Timer 45 and return.\r\nTimer 46: Parse “ReReReRe.htm” (downloaded by Timer 45)\r\nTimer 46 goes through all the different running instances of instrumented IE, looking at the title of each HTM\r\npage. The main interest here is “r!r!r!r!”.\r\nThis page is the ReReReRe.htm file downloaded by Timer 45. Timer 46 looks for a special EOF (End Of File)\r\nmarker: “tamamshodfile”. This marker is used by the infostealer to make sure the htm page was fully downloaded.\r\nOnce the page has been confirmed as valid, it looks for the textarea id S1 which holds double Base64 encoded PE\r\nFiles.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 18 of 23\n\nThe Base64 encoded data is saved as: ASLASLKK223.dll.\r\nTimer 47: Double decoding of Base64 encoded payload from ReReReRe.htm\r\nNote: Timer 46 saves the payload as ASLASLKK223.dll.\r\nSince the payload file is double encoded, the decoding is performed in two steps:\r\nASLASLKK223.dll is decoded to ASLASLKK224.dll to get a single encoded Base64 file.\r\nASLASLKK224.dll is decoded to “res.exe” : Final PE file.\r\nRes.exe is a copy of the Resource Hacker utility. ASLASLKK224.dll is deleted.\r\nThe use of Res.exe is described in the analysis of Timer 39 below.\r\nOnce Timer 47 has finished enumerating all the IE instances, it will call a cleaning routine. It searches for ” –\r\nr!r!r!r! – Windows Internet Explorer” and different variants described in Timer 45 and sends a “WM_Close”\r\nMessage to IE Windows in order to close them.\r\nAmong all those captions, it also searches for ” – 404 – File or directory not found.” and variants of 404 pages.\r\nOnce the cleaning is completed, Timer 47 disables itself and returns.\r\nTimer 49: Visit the SeSeSeSe.htm page\r\nTimer 49 is almost identical to Timer 45. The only difference is the page visited: SeSeSeSe.htm instead of\r\nReReReRe.htm\r\nSee the Timer 45 description for details.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 19 of 23\n\nTimer 50: Parse “SeSeSeSe.htm” (downloaded by Timer 49)\r\nTimer 50 is almost identical to Timer 46. The only difference is the page parsed: SeSeSeSe.htm instead of\r\nReReReRe.htm and local file names. The double encoded payload is saved as “ASLASLKK2231.dll”.\r\nSee the Timer 46 description for details.\r\nTimer 51: Double decoding of Base64 encoded payload from SeSeSeSe.htm\r\nNote: Timer 50 saves the payload as ASLASLKK2231.dll.\r\nSince the payload file is double encoded, the decoding is performed in two steps:\r\nASLASLKK2231.dll is decoded to ASLASLKK2241.dll to get a single encoded Base64 file.\r\nASLASLKK2241.dll is decoded to “Ladine.dll”: final PE file.\r\nNote: At the time of writing, the SeSeSeSe.htm page had been removed from the C\u0026C server.\r\nA C\u0026C server used by older variants of the infostealer is still available and the old page name was “SSSS.htm”.\r\nThe embedded file is a template of a downloader executable (see Timers 35, 36, 37, 38 and 39 for further\r\ninformation).\r\nOnce Timer 51 has finished enumerating all the IE instances, it will call a cleaning routine. It searches for ” –\r\ns!s!s!s! – Windows Internet Explorer” and different variants described in Timer 45, and sends a “WM_Close”\r\nMessage to IE Windows in order to close them.\r\nAmong all those captions, it also searches for ” – 404 – File or directory not found.” and variants of 404 pages.\r\nOnce the cleaning is completed, Timer 51 disables itself and returns.\r\nBETA/NON-WORKING FEATURES: New executable generation\r\nThere are a few timers in the infostealer that are related to a missing file. I managed to find a copy of the missing\r\nfile from an older command and control server, in order to understand the intentions of the authors.\r\nThe missing file is downloaded by Timer 50: SeSeSeSe.htm. It’s not present on the current C\u0026C servers.\r\nIf we were to replace the SeSeSeSe.htm with an old copy (originally SSSS.htm), Timer 51 would produce a file\r\ncalled “Ladine.dll”, which is a template executable of the Trojan downloader used to install the infostealer.\r\nTimer 52: Copy Ladine.dll to “Soltanik.exe”\r\nTimer 52 makes a copy of “Ladine.dll” under the name “soltanik.exe”, which is the template file.\r\nTimer 35: Clean files from Timer 39\r\nTimer 35 is disabled. A special BOTID is created by concatenating “CoolDiskGo(” with “BOTID_TMP)”, e.g.:\r\nCoolDiskGo(MYCOMPUTER-8712422C6C7704EF)\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 20 of 23\n\nTimer 35 puts the C\u0026C IP address in a global variable that will be used by Timer 38.\r\nTimer 35 tries to delete the following several files created by Timer 39: 1.txt, res.ini, res.log, Icon_1.ico,output.rc\r\nand server.exe.\r\nIt does several other things which are not relevant to what I describe here, so I’ve omitted any reference to those\r\nactions.\r\nTimer 36 is enabled before returning.\r\nTimer 36: Enable Timer 37 if 1.txt isn’t found – logic/code bug\r\nTimer 36 is disabled upon execution. If “1.txt” isn’t present, Timer 37 is enabled. Otherwise, it calls a Base64\r\ndecoding function. 1.txt must be a valid Base64 encoded stream of bytes; otherwise, an exception occurs and\r\nTimer 36 returns.\r\nTimer 37: Update resource for the template downloader: Soltanik.exe\r\nTimer 37 is disabled upon execution. A structure exception handler is installed before reading 1.txt.\r\nIn the event of an exception the SEH handler will enable Timers 42, 34, 33, 35, and Timer 37 will return.\r\nTimer 37 expects 1.txt to be present and here is the logic bug. Timer 37 is only enabled when 1.txt isn’t present,\r\nby Timer 36. Let’s ignore the reasons for its creation and continue analyzing the intentions of the authors.\r\nTimer 37 calls the BeginUpdateResource (with the bDeleteExistingResources parameter set to 0), and start\r\nupdating the resources of the template executable (soltanik.exe) in RCDATA.\r\nA MAHDI entry is added, with the Base64 content from 1.txt. This works in exactly the same way as the\r\ndownloaders with social engineering features.\r\nTimer 38 is enabled, and Timer 37 returns.\r\nNote: At the end of Timer 37, Soltanik has been modified to have a new resource: MAHDI.\r\nTimer 38: Update more resources from the template downloader (Soltanik.exe)\r\nSeveral entries are added to RCDATA:\r\nShelikn : Special BotID generated by Timer 35\r\nSiteW: C\u0026C IP address\r\nBind: Empty (according to analysis of the downloaders that use social engineering, it should be the\r\nextension of the embedded file dropped to social engineering victims. If MAHDI contains a Base64\r\nencoded picture, Bind should be set to .JPG).\r\nFilee: SCR\r\nRoze: 0\r\nOnce the resources have been updated, Timer 39 is enabled and Timer 38 returns.\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 21 of 23\n\nTimer 39: Generate a final binary: Server.exe with updated icon\r\nAt the end of Timer 38, soltanik.exe has been fully updated with new resources. Upon execution, Timer 39\r\ndisables itself and starts generating a special command line for the Resource Hacker tool that was created as\r\n“Res.exe” by Timer 47.\r\nThe command line is the following:\r\nThere is a bug in the routine. An executable name is missing right after “-extract”.\r\nThe command line dumps the Main Icon to disk (Icon_1.ico) and creates a file called “output.rc”.\r\nAt this point, it is impossible to know which file was meant to be used as the source of a new icon. For the sake of\r\nour analysis, let’s pretend the bug doesn’t exist and that a valid file name was provided.\r\nAfterwards, a second command line is passed to “Res.exe”:\r\nThis final command line will generate Server.exe, a copy of soltanik.exe whose icon has been changed to the one\r\nextracted in the previous command.\r\nServer.exe is now fully updated. Its resources are filled, and its icon changed. It’s not clear why the authors did\r\nthis, but despite all the bugs it was possible to understand the overall aim of the routine: to create a Server.exe file\r\nfrom soltanik.exe with a new icon and added resources. What happens to Server.exe? Nothing, this is a non-working feature. It appears Madi has the ability to generate new downloaders, at least, in theory.\r\nThe 7 remaining timers won’t be described as they are of little interest.\r\nConclusions\r\nIn this article we closely analyzed the infostealer used in the Madi campaign. The coding style and the usage of\r\nDelphi, together with the programming techniques indicate a rudimentary approach.\r\nMost of the data-stealing actions and communication with the C\u0026C servers take place via external files, which is\r\nrather messy. Whoever coded it is probably still reading through the first chapters of their Delphi manuals.\r\nThis is maybe why it is surprising to note its effectiveness, considering the data received from the sinkhole.\r\nDuring the monitored period, a little over 800 victims were connected to the servers. All of them fell prey to the\r\nvarious social engineering techniques used by the malware.\r\nTo sum up, we can say the following:\r\nthe components of the Madi campaign are surprisingly unsophisticated\r\nno exploits or advanced 0-day techniques are used anywhere in the malware\r\ndespite that, the overall success of the campaign is surprisingly high\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 22 of 23\n\nnevertheless, we should remember that even low quality malware can steal data\r\nMadi was a low investment, high profit project\r\nits authors remain unknown\r\nWe will continue to monitor the Madi malware and update you on our findings in the future.\r\nSource: https://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nhttps://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/\r\nPage 23 of 23",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://securelist.com/the-madi-infostealers-a-detailed-analysis/36609/"
	],
	"report_names": [
		"36609"
	],
	"threat_actors": [
		{
			"id": "322a0ef1-136b-400e-89d0-0d62ee2bd319",
			"created_at": "2023-01-06T13:46:38.662109Z",
			"updated_at": "2026-04-10T02:00:03.05924Z",
			"deleted_at": null,
			"main_name": "Madi",
			"aliases": [],
			"source_name": "MISPGALAXY:Madi",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "b07fec96-80cd-4d92-aa52-a26a0b25b7c2",
			"created_at": "2022-10-25T16:07:23.826594Z",
			"updated_at": "2026-04-10T02:00:04.760416Z",
			"deleted_at": null,
			"main_name": "Madi",
			"aliases": [
				"Mahdi"
			],
			"source_name": "ETDA:Madi",
			"tools": [
				"Madi"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434477,
	"ts_updated_at": 1775826689,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/857a5eda4d401e11cd51d7b8357e9f7c4a11d43a.pdf",
		"text": "https://archive.orkl.eu/857a5eda4d401e11cd51d7b8357e9f7c4a11d43a.txt",
		"img": "https://archive.orkl.eu/857a5eda4d401e11cd51d7b8357e9f7c4a11d43a.jpg"
	}
}