Deep Analysis of QBot Banking Trojan By Abdallah Elshinbary Published: 2020-07-15 · Archived: 2026-04-05 22:00:02 UTC QBot is a modular information stealer also known as Qakbot or Pinkslipbot. It has been active for years since 2007. It has historically been known as a banking Trojan, meaning that it steals financial data from infected systems. Infection FlowPermalink QBot can be delivered in various different ways including Malspam (Malicious Spam) or dropped by other malware families like Emotet. The infection flow for this campaign is as follows: First, the victim receives a phishing email with a link to a malicious zip file. The zip file contains a very obfuscated VBS file which downloads and launches Qbot executable. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 1 of 23 The VBS file tries to download Qbot from different places: http://st29[.]ru/tbzirttmcnmb/88888888.png http://restaurantbrighton[.]ru/uyqcb/88888888.png http://royalapartments[.]pl/vtjwwoqxaix/88888888.png http://alergeny.dietapacjenta[.]pl/pgaakzs/88888888.png http://egyorg[.]com/vxvipjfembb/88888888.png Notice the misleading URL, it looks like it’s downloading a PNG image but the raw data says something else. UnpackingPermalink QBot is packed with a custom packer, but the unpacking process is really simple. It allocates memory for the unpacked code using VirtualAlloc() and changes memory protection using VirtualProtect() . So we just need 2 breakpoints at VirtualAlloc() and VirtualProtect() . https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 2 of 23 Encrypted StringsPermalink Most of QBot strings are encrypted (stored in a continuous blob) and they are decrypted on demand. The decryption routine accepts one argument which is the index to the string then it XORs it with a hardcoded bytes array until it encounters a null byte. We can use IDAPython to decrypt the strings and add them as comments. import idc import idautils dec_routine = 0x4065B7 enc_strings = 0x40B930 bytes_arr = 0x410120 def decrypt_string(idx): if idx >= 0x36F4: return # out of bounds res = "" while True: c = idc.get_wide_byte(enc_strings+idx) ^ idc.get_wide_byte(bytes_arr + (idx&0x3F)) if c == 0: break res += chr(c) idx += 1 return res xrefs = idautils.CodeRefsTo(dec_routine, 0) for x in xrefs: ea = idc.prev_head(x) t = idc.get_operand_type(ea, 1) if t == idc.o_imm: idx = idc.get_operand_value(ea, 1) https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 3 of 23 dec = decrypt_string(idx) idc.set_cmt(ea, dec, 1) And here is the result, that’s much easier to work with. This should take care of most of the strings, the rest of strings indexes are calculated dynamically at runtime. We decrypt all strings by looping through the encrypted blob and decrypt strings one by one. idx = 0 while idx < 0x36F4: dec = decrypt_string(idx) idx += len(dec)+1 print(dec) Anti-AnalysisPermalink QBot spawns a new process of itself with the "/C" parameter, this process is responsible for doing Anti-Analysis checks. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 4 of 23 The parent process checks the exit code of this spawned process. If the exit code is not 0, it means that QBot is being analyzed (and so it exits). So let’s go over the anti-analysis techniques. Checking VMPermalink In VMWare, communication with the host is done through a specific I/O port (0x5658) , so QBot uses the in assembly instruction to detect VMWare by reading from this port and checking the return value in ebx if it’s equal to VMXh (VMware magic value). If we are outside VMWare, a privilege error occurs and this code will return 0. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 5 of 23 Another Anti-VM trick is to check hardware devices against known devices names used by VMs and Sandboxes. Here is the list of devices names. Expand to see more   VMware Pointing   VMware Accelerated   VMware SCSI   VMware SVGA   VMware Replay   VMware server memory Checking ProcessesPermalink QBot loops through running processes and compares their executable names against known analysis tools. Expand to see more   Fiddler.exe   samp1e.exe   sample.exe   runsample.exe   lordpe.exe   regshot.exe Checking DLLsPermalink Sandbox detection can be done by enumerating loaded DLLs and comparing them against known DLLs used by sandboxes. Here it’s just using 2 of them. ivm-inject.dll # Buster Sandbox Analyzer SbieDll.dll # SandBoxie Checking FilenamePermalink Some sandboxes may change the sample file name. So QBot checks if its process name contains one of these strings. sample mlwr_smpl artifact.exe Checking CPUPermalink https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 6 of 23 The last check is done using CPUID instruction. First it is executed with EAX=0 to get the CPU vendor and compares it with GenuineIntel (Intel processor). Then it is executed with EAX=1 to get the processors features. On a physical machine the last bit will be equal to 0. On a guest VM it will equal to 1. Back To ParentPermalink After the Anti-Analysis checks, QBot drops a copy of itself along with a configuration file at "%APPDATA%\Microsoft\" . Finally, QBot starts the dropped copy in a new process and overwrites itself with a legitimate executable, here it’s "calc.exe" . Configuration FilePermalink The dropped configuration file is accessed frequently by Qbot, this file is RC4 encrypted. By setting a breakpoint before the contents of the file gets encrypted I got the following data: https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 7 of 23 Field Description 10=spx143 Campaign ID 11=2 Number of hardcoded C2 1=13.59.00-24/06/2020 Date of Qbot install in HH:MM:ss-dd/mm/yyyy 2=1592996340 Victim Qbot install 50=1 N/A 5=VgBCAE8AWABTAFYAUgA7ADIA Victim network shares 38=1593047244 Last victim call to C2 (Unix time) 45=187.163.101.137 C2 IP 46=995 C2 port 39=45.242.76.104 Victim external IP 43=1593006172 Time of record (Unix time) 49=1 N/A PersistencePermalink QBot achieves persistence by creating a new registry value under the key "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" . It also registers a scheduled task that runs every 5 hours. Process InjectionPermalink QBot tries to inject its unpacked code in one of these processes ("explorer.exe", "mobsync.exe", "iexplorer.exe") and it uses Process Hollowing technique to achieve that. It first starts a new suspended process with CreateProcessW() then it writes the injected code into the target process using ZwCreateSection() , ZwMapViewOfSection() and ZwWriteVirtualMemory() . Finally it sets the thread context to jump to the injected code and resume execution with ResumeThread() . Core ModulePermalink https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 8 of 23 The injected code loads and decrypts one of its resources "307" . After dumping it, I found out that it’s a DLL (this is the core module). From now on, we will be analyzing the core DLL of QBot. The core module has 2 resources both RC4 encrypted. The first resource gets loaded into memory then RC4 decrypted. The contents of the decrypted resource are: 10=spx143 (Campaign ID) 3=1592482956 (Timestamp) https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 9 of 23 After some digging, I found out how the resources are decrypted. The first 20 bytes of each resource are the RC4 key of this resource, and the rest are the actual encrypted data. So by using this find, we can decrypt the other resource "311" . Great!!! Now we have the list of C2 servers (150 servers!). The reason there is many controllers is that these are actually just proxies of infected bots acting as intermediate nodes between the victim and the real C2 and thus hiding the backend infrastructure of the attacker. So it works like this: https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 10 of 23 C2 CommunicationPermalink QBot obfuscates its communication with the C2 server by encrypting the payloads using RC4 and encoding the result using Base64. The communication is also done over SSL, you can notice that the traffic has unusual certificate issuer data. We can use Fiddler to intercept and decrypt the HTTPS traffic. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 11 of 23 The RC4 key for encrypting the payload is the SHA1 hash of the first 16 bytes of the Base64-decoded payload + a hardcoded salt (The salt is stored as an encrypted string). Here is an implementation of the decryption algorithm: HARDCODED_SALT = b"jHxastDcds)oMc=jvh7wdUhxcsdt2" # decrypted string def decrypt_payload(encrypted_blob): b64_decoded = base64.b64decode(encrypted_blob) decryption_key = b64_decoded[:0x10] + HARDCODED_SALT sha1hash = hashlib.sha1() sha1hash.update(decryption_key) decryption_key_hash = sha1hash.digest() rc4 = ARC4(decryption_key_hash) return rc4.decrypt(b64_decoded[0x10:]) The decrypted payload is in JSON form. Decrypted C2 Request: {“8”:9,”1”:17,”2”:”pnmfcq111232”} Decrypted C2 Response: {“8”:5,”16”:770897804,”39”:”V4UnoDQSEblewhh63UfUqAns”,”38”:1} Commands ListPermalink After establishing communication, the C2 server will send commands indexes to be executed. Here is the list of commands and their corresponding indexes (I have renamed the important commands). https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 12 of 23 It’s worth mentioning that dynamic imports of the core DLL are stored in the same format as commands " " , the API and DLL indexes are passed to the string decryption routine which returns their corresponding names then it uses LoadLibrary and GetProcAddress to resolve the imports. Let’s go through some of the interesting commands. Command 13: Lateral MovementPermalink https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 13 of 23 QBot can spread through the network by enumerating network shares using WNetOpenEnumW() and WNetEnumResourceW () then it drops a copy of Qbot into the shared folders. Then the dropped executable is registered as an auto-start service on the target machine. The names for the service and the dropped file are randomly generated strings. Finally, Qbot deletes the created service and dropped file from the target machine (as it’s successfully infected). Command 21: Collecting Installed ApplicationsPermalink QBot can collect installed applications by enumeration subkeys of the registry key "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" . https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 14 of 23 The collected data is appended to the end of a string containing additional information about the victim’s machine and time of collection. t=i1 time=[] ext_ip=[] dnsname=[?] hostname=[] user=[] domain=[] is_admin=[] os=[] qbot_version=[] install_time= [] exe=[] prod_id=[NULL] iface_n=[/] UP] soft=[||...] Example of collected data: Then the data is RC4 encrypted and written to "wdqlxw32.dll" at the same directory of QBot. Finally, "wdqlxw32.dll" is Zlib compressed and RC4 encrypted again then it’s saved to "cwdqlxw32.dll" and the original "wdqlxw32.dll" is deleted. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 15 of 23 The compressed file is then transfered to the C2 server (RC4 encrypted and Base64 encoded) in the key "36" and the compressed file "cwdqlxw32.dll" is also deleted. Command 31: Fetching PluginsPermalink As we said before, QBot is known to be a modular malware. It can load additional plugins received from the C2 server (plugins are RC4 encrypted and Base64 encoded). QBot tries to inject the received plugin in 3 different processes depending on the machine architecture. It creates a new suspended process then writes the plugin to the process memory using WriteProcessMemory() and then resumes the injected process. https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 16 of 23 At the time of writing this, Qbot has 3 different plugins (“Password grabber”, “Cookie grabber”, “UPnP module”). ConclusionPermalink QBot is considered to be a sophisticated malware, it’s receiving regular updates from time to time and it’s not likely to go away anytime soon. There is still more features that I didn’t cover such as WebInjects so maybe I will come back to Qbot later I guess :) IOCsPermalink HashesPermalink VBS File: b734caf792c968ca1870c3ec7dda68ad5dc47fef548751afb8509752c185a756 QBot: 112a64190b9a0f356880eebf05e195f4c16407032bf89fa843fd136da6f5d515 URLsPermalink http://st29[.]ru/tbzirttmcnmb/88888888.png http://restaurantbrighton[.]ru/uyqcb/88888888.png http://royalapartments[.]pl/vtjwwoqxaix/88888888.png http://alergeny.dietapacjenta[.]pl/pgaakzs/88888888.png http://egyorg[.]com/vxvipjfembb/88888888.png C2 DomainsPermalink 39.36.254.179:995 24.139.132.70:443 24.202.42.48:2222 72.204.242.138:443 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 17 of 23 172.242.156.50:995 72.204.242.138:20 68.174.15.223:443 74.193.197.246:443 96.56.237.174:990 64.19.74.29:995 70.168.130.172:443 189.236.166.167:443 68.4.137.211:443 76.187.8.160:443 76.86.57.179:2222 73.226.220.56:443 67.250.184.157:443 75.183.171.155:3389 173.172.205.216:443 173.3.132.17:995 172.78.30.215:443 207.255.161.8:32103 75.137.239.211:443 68.49.120.179:443 206.51.202.106:50003 82.127.193.151:2222 207.255.161.8:2222 207.255.161.8:2087 24.152.219.253:995 187.19.151.218:995 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 18 of 23 197.37.48.37:993 188.241.243.175:443 72.88.119.131:443 89.137.211.239:443 108.30.125.94:443 187.163.101.137:995 100.19.7.242:443 45.77.164.175:443 80.240.26.178:443 66.208.105.6:443 207.246.75.201:443 199.247.22.145:443 199.247.16.80:443 95.77.223.148:443 68.60.221.169:465 5.107.220.84:2222 41.228.212.22:443 86.233.4.153:2222 68.200.23.189:443 201.146.127.158:443 79.114.199.39:443 87.65.204.240:995 71.74.12.34:443 217.162.149.212:443 195.162.106.93:2222 75.165.112.82:50002 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 19 of 23 201.248.102.4:2078 96.41.93.96:443 89.247.216.127:443 84.232.238.30:443 103.238.231.40:443 174.34.67.106:2222 98.115.138.61:443 91.125.21.16:2222 84.247.55.190:443 193.248.44.2:2222 74.135.37.79:443 78.96.190.54:443 86.126.97.183:2222 2.50.47.97:2222 68.39.160.40:443 96.232.203.15:443 86.144.150.29:2222 71.220.191.200:443 24.231.54.185:2222 80.14.209.42:2222 24.164.79.147:443 70.183.127.6:995 47.153.115.154:993 184.180.157.203:2222 50.104.68.223:443 67.165.206.193:995 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 20 of 23 200.113.201.83:993 47.153.115.154:465 24.42.14.241:995 189.160.203.110:443 188.27.76.139:443 207.255.161.8:32102 49.207.105.25:443 71.210.177.4:443 117.242.253.163:443 50.244.112.106:443 69.92.54.95:995 41.34.91.90:995 72.204.242.138:53 41.97.138.74:443 72.29.181.77:2078 71.88.168.176:443 2.50.171.142:443 67.83.54.76:2222 86.125.145.90:2222 47.153.115.154:995 24.122.157.93:443 47.146.169.85:443 72.181.9.163:443 187.155.74.5:443 71.209.187.4:443 74.75.216.202:443 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 21 of 23 24.44.180.236:2222 24.43.22.220:993 108.188.116.179:443 100.4.173.223:443 76.170.77.99:443 70.95.118.217:443 134.0.196.46:995 68.225.56.31:443 72.204.242.138:32102 72.204.242.138:50001 108.190.151.108:2222 72.204.242.138:465 50.244.112.10:443 173.22.120.11:2222 24.43.22.220:995 24.43.22.220:443 92.17.167.87:2222 72.209.191.27:443 72.204.242.138:80 72.204.242.138:443 71.187.170.235:443 96.56.237.174:32103 71.187.7.239:443 184.98.104.7:995 70.124.29.226:443 137.99.224.198:443 https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 22 of 23 73.23.194.75:443 151.205.102.42:443 64.224.76.152:443 72.204.242.138:32100 173.187.101.221:443 72.179.13.59:443 208.93.202.49:443 70.174.3.241:443 96.37.137.42:443 76.111.128.194:443 67.209.195.198:3389 61.3.184.27:443 24.42.14.241:443 74.56.167.31:443 5.193.61.212:2222 117.216.177.171:443 ReferencesPermalink Demystifying QBot Banking Trojan - BSides Belfast https://www.virusbulletin.com/virusbulletin/2017/06/vb2016-paper-diving-pinkslipbots-latest-campaign https://www.fortinet.com/blog/threat-research/deep-analysis-qbot-campaign https://www.vkremez.com/2018/07/lets-learn-in-depth-reversing-of-qakbot.html https://www.hexacorn.com/blog/2016/07/01/enter-sandbox-part-12-the-library-of-naughty-libraries/ https://www.cyberbit.com/blog/endpoint-security/anti-vm-and-anti-sandbox-explained/ Source: https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ https://n1ght-w0lf.github.io/malware%20analysis/qbot-banking-trojan/ Page 23 of 23