This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def nymaim_decrypt(self, raw, from_raw, length): | |
| from_va = from_raw + self.image_base | |
| xsize = from_va - self.off | |
| cur_key = self.key | |
| if xsize < 0: | |
| raise RuntimeError("raw too small - min is " + hex(self.off - self.image_base)) | |
| for _ in range(xsize / 4): | |
| cur_key = (cur_key + self.xstep) & 0xffffffff | |
| r = '' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def nymaim_config_crypt(self, mem, ndx): | |
| """decrypt final config (read keys and length and decrypt raw data)""" | |
| key0 = mem.dword(ndx) | |
| key1 = mem.dword(ndx+4) | |
| len = mem.dword(ndx+8) | |
| raw = mem.read(ndx + 12, len) | |
| prev_chr = 0 | |
| result = '' | |
| for i, c in enumerate(raw): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| struct chunk { | |
| uint32_t type; | |
| uint32_t length; | |
| char data[chunk_length]; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def parse_static_config(blob): | |
| i = 0 | |
| while i < len(blob): | |
| chunk_type = blob[i:i+4] # chunk type, also called "hash" or "chunk hash" in this article | |
| chunk_len = from_uint32(blob[i+4:i+8]) | |
| chunk_content = blob[i+8:i+8+chunk_len] | |
| process_chunk(chunk_type, chunk_content) # this function should process every type of chunk | |
| i += 8 + chunk_len |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| if hash == self.CFG_URL: # '48c2026b': | |
| parsed['urls'] += [{'url': append_http(x)} for x in filter(None, map(get_domainc, raw.split(';')))] | |
| elif hash == self.CFG_DGA_HASH: # 'd9aea02a': | |
| parsed['dga_hash'] = [uint32(h) for h in chunks(raw, 4)] | |
| elif hash == self.CFG_DOMAINS: # '095d4b1d': | |
| parsed['domains'] += map(lambda x: {'cnc': x}, filter(None, map(get_domainc, raw.split(';')))) | |
| elif hash == self.CFG_ENC_KEY: # '510be622': | |
| parsed['encryption_key'] = raw | |
| ... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def dga_single(self, state): | |
| name = '' | |
| len = self.getbyte(state, 8) + 5 | |
| for i in range(len): | |
| r = self.getbyte(state, 0xFFFFFFFF) | |
| c = self.getbyte(state, 26) + 0x61 | |
| name += chr(c) | |
| n = 0 | |
| while n == 0: | |
| n = self.getbyte(state, 5) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ╰─$ strings decrypted_nymaim | grep -E "#!#|Firewall" | |
| #!#*|Action=Allow|#* | |
| #!#*|Action=Block|#* | |
| #!#*|Active=TRUE|#* | |
| #!#*|Active=FALSE|#* | |
| #!#*|Dir=In|#* | |
| #!#*|Dir=Out|#* | |
| #!#*|Profile=Private|#* | |
| #!#*|Profile=Public|#* | |
| #!#*|LPort=#* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ╰─$ strings decrypted_nymaim | grep -E "PortMap|upnp" | |
| DeletePortMapping | |
| urn:schemas-upnp-org:service:WANPPPConnection:1 | |
| urn:schemas-upnp-org:device:InternetGatewayDevice:1 | |
| GetSpecificPortMappingEntry | |
| upnp:rootdevice | |
| AddPortMapping | |
| AddAnyPortMapping | |
| urn:schemas-upnp-org:service:WANIPConnection:1 | |
| NewPortMappingDescription |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ╰─$ strings decrypted_nymaim | grep -E "nginx" -B 4 | |
| HTTP/1.1 200 OK | |
| Connection: close | |
| Content-Length: %u | |
| Content-Type: application/octet-stream | |
| Server: nginx/1.9.4 | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def nymaim_decrypt(key, raw_bytes): | |
| nibble0 = raw_bytes[0] & 0xF | |
| nibble1 = raw_bytes[1] & 0xF | |
| salt = raw_bytes[2:2+nibble0] | |
| password = key + salt | |
| data = raw_bytes[2+nibble0:len(raw_bytes)-nibble1] | |
| decrypted = rc4_decrypt(password, body) | |
| decrypted_len = struct.unpack('<I', decrypted[:4])[0] | |
| assert decrypted_len == len(decrypted - 4) |