SmokeLoader Triage
Taking a look how Smoke Loader works
Overview
Samples
- Packed parent cef4f5f561b5c481c67e0a9a3dd751d18d696b61c7a5dab5ebb29535093741b4
- Unpacked SmokeLoader 041a05dd902a55029449bf412cedbe59a593f8d4e67d4ae37cf7a928c92f22ca
SmokeLoader Background
This SmokeLoader sample is on MalwareBazaarand through sandbox runs we know that is was used to download Vidar. From JoeSandbox public report we know we should find the following config in this loader
{
"C2 list": [
"http://piratia.su/tmp/",
"http://piratia-life.ru/tmp/",
"http://diewebseite.at/tmp/",
"http://faktync.com/tmp/",
"http://mupsin.ru/tmp/",
"http://aingular.com/tmp/",
"http://mordo.ru/tmp/"
]
}
References
Stage 2
Opaque predicate deobfuscation
From this blog we have a simple jmp fix script.
import idc
ea = 0
while True:
ea = min(idc.find_binary(ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN, "74 ? 75 ?"), # JZ / JNZ
idc.find_binary(ea, idc.SEARCH_NEXT | idc.SEARCH_DOWN, "75 ? 74 ?")) # JNZ / JZ
if ea == idc.BADADDR:
break
idc.patch_byte(ea, 0xEB) # JMP
idc.patch_byte(ea+2, 0x90) # NOP
idc.patch_byte(ea+3, 0x90) # NOP
``
Once we fix the jmps we need to nop out the junk code between the code to allow IDA to convert this into a function
```python
import idaapi
start = 0x00402DDD
end = 0x00402EBF
ptr = start
while ptr <= end:
next_ptr = next_head(ptr)
junk_bytes = next_ptr - ptr
if ida_bytes.get_bytes(ptr, 1) == b'\xeb':
idaapi.patch_bytes(ptr, junk_bytes * b'\x90')
ptr = next_ptr
Or, we could use this excellent script from @anthonyprintup
import ida_ua
import ida_name
import ida_bytes
def decode_instruction(ea: int) -> ida_ua.insn_t:
instruction: ida_ua.insn_t = ida_ua.insn_t()
instruction_length = ida_ua.decode_insn(instruction, ea)
if not instruction_length:
return None
return instruction
def main():
begin: int = ida_name.get_name_ea(idaapi.BADADDR, "start")
end: int = begin + 0xE2
instructions: dict[int, ida_ua.insn_t] = {}
# Undefine the current code
ida_bytes.del_items(begin, 0, end)
# Follow the control flow and create instructions
instruction_ea: int = begin
while instruction_ea <= end:
if instruction_ea not in instructions.keys():
instruction: ida_ua.insn_t = ida_ua.insn_t()
instruction_length: int = ida_ua.create_insn(instruction_ea, instruction)
else:
instruction: ida_ua.insn_t = decode_instruction(instruction_ea)
instruction_length: int = instruction.size
if not instruction_length:
print(f"Failed to create an instruction at address {instruction_ea=:#x}")
return
# Append the current instruction address to the list
instructions[instruction.ip] = instruction
# Handle unconditional jumps
current_instruction_mnemonic: str = instruction.get_canon_mnem()
next_instruction: ida_ua.insn_t | None = decode_instruction(instruction_ea + instruction.size)
if next_instruction is not None:
next_instruction_mnemonic: str = next_instruction.get_canon_mnem()
if (current_instruction_mnemonic == "jnz" and next_instruction_mnemonic == "jz") or \
(current_instruction_mnemonic == "jz" and next_instruction_mnemonic == "jnz"):
# Unconditional jump detected
assert instruction.ops[0].type == ida_ua.o_near
instruction_ea = instruction.ops[0].addr
ida_ua.create_insn(next_instruction.ip)
instructions[next_instruction.ip] = next_instruction
continue
if current_instruction_mnemonic == "jmp":
assert instruction.ops[0].type == ida_ua.o_near
instruction_ea = instruction.ops[0].addr
else:
instruction_ea += instruction.size
# NOP the remaining instructions
for ea in range(begin, end):
skip: bool = False
for _, instruction in instructions.items():
if ea in range(instruction.ip, instruction.ip + instruction.size):
skip = True
break
if skip:
continue
# Patch the address
ida_bytes.patch_bytes(ea, b"\x90")
if __name__ == "__main__":
main()
After this we can see that the next function address is built using some stack/ret manipulation.
Generic Opaque Predicate Patching
There is also this nice generic patching script from Alex: nopme.py.
Function Decryption
Some functions are encrypted. We can find the first one by following the obfuscated control flow until the first call
. This call calls into a function which then calls the decryption function. The decryption function takes a size and a offset to the function that needs to be decrypted. The size is placed in the ecx
register, and the function offset follows the call.
mov ecx, 0E7h ; 'ç
The decryption itself is a single byte xor but the decryption key is moved into the edx
register as a full DWORD (we only used the LSB).
mov edx, 76186250h
From this blog we have a simple deobfuscation script updated for our sample. This script didn't perform well for some reason so we ended up manually decrypting the functions!
import idc
import idautils
def xor_chunk(offset, n):
ea = 0x400000 + offset
for i in range(n):
byte = ord(idc.get_bytes(ea+i, 1))
byte ^= 0x50
idc.patch_byte(ea+i, byte)
def decrypt(xref):
call_xref = list(idautils.CodeRefsTo(xref, 0))[0]
while True:
if idc.print_insn_mnem(call_xref) == 'push' and idc.get_operand_type(call_xref, 0) == idaapi.o_imm:
n = idc.get_operand_value(call_xref, 0)
break
if idc.print_insn_mnem(call_xref) == 'mov' and idc.get_operand_type(call_xref, 1) == idaapi.o_imm:
n = idc.get_operand_value(call_xref, 1)
break
call_xref = prev_head(call_xref)
n = idc.get_operand_value(call_xref, 0)
offset = (xref + 5) - 0x400000
xor_chunk(offset, n)
idc.create_insn(offset+0x400000)
ida_funcs.add_func(offset+0x400000)
xor_chunk_addr = 0x00401118 # address of the xoring function
decrypt_xref_list = idautils.CodeRefsTo(xor_chunk_addr, 0)
for xref in decrypt_xref_list:
decrypt(xref)
API Hashing
According to this blog we are expecting to see some API hashing using the djb2 algorithm. We can try to find this function by searching for the constant 0x1505.
Though the djb2 algorithm is used for the API hashing the malware also encrypts the hashes with a hard coded XOR key. In our sample the key is 0x76186250.
import requests
hash = 0x8161735f
def hash_djb2(s):
hash = 5381
for x in s:
hash = (( hash << 5) + hash) + x
return hash & 0xFFFFFFFF
print(hex(hash_djb2(b'NtTerminateProcess\x00') ^ 0x76186250))
Extract Stage 3
Decryption
There is a 32-bit and a 64-bit version of stage 3 stored consecutivly in the binary. The data is encrypted with a hard coded 4-byte XOR key, the decryption must be a multiple of four. The trailing bytes (if any) are then decrypted with a single byte XOR. In our sample the DWORD key is 0x76186250 and the single byte key is 0x50.
data_string = '5058187647a21889fa5d103a51605c8eb0621a575b63149f64673087b5753166bb323066f2465570508c1e9f308e1c5d52dc136676a93b31549d0c9e008d6c3505292b1919566c995437f056be82f3023592574e888a58611262e79fa76387886fa5bcdd7fcb556510f48f569c5dcc79d5fd2ef15f87bc8a1cdf2605b6775d048d5ac6ac2286e2481bd8ec2b50f8e85d4c825f21e4c5f30012fd31f395d92876562f7a4b1c09e5d519dbaf7f9b5ecb86173edc19adf5e7e26fb7d0c8529b490a40434ff874b4bf14a7bc9a2f51a9aedc7268c6d775b4015e9e5d19c6d3586f26772cdf86d5f867ab0860c969c52c4b96c842930fd12e3c775062017569c5442db6e89cc9d8f241469d7477a86ee19adeb910fe4ed083a16cc9d9a42a50620e7ec3a7661d4c42dbded5c36f8b663f4d15db809b3b7d6499f5c1c309a82e6200917148992885fa01f9c3dfd60a67373d5fe1ba3b2cb1ac5aaf9f336e0bf353998fafe9920f728065e14b2570ccaff26be66a2dada4bdf16afb45303d5e7ff159d243fa65c1653b79be0ba67eb30b982bf465da01f265daae13fedfae13d4e50f31476f223754f28ead67bf3f9bba345242758e0ee22d8747ad08abc5e346580ef3b4ebb43a13e826208febcc5f2fefe2e8d3a999d2c02e7bd24e7d7ee4fc620016d26e14229bdc97827e212fd144328014d2e4fc7eedadc5e3936d3d8c50751488e638996fa3008a85aac789029dc797427bd2a793a196ab4d959ba1539896e55d8dd1a47dd3ea83fe70e77f51bfc2805be89da250a2d9c87a9e8bda6ec5c19740db077c05a53aab5f8706a15d81fe44927cfebc19234e8f6fa3fb942c9bfaff4092f095fe704ea97ba9d9b6789bd3bf78e3d6ad48dc96921384bcb55599a1b35398bcb94d95eed376acaf8978623868cad1fc504f7e34b09b82e45571a3e59f80e32ca74480e48602aedd3941b8109ce88dd6b85679f4c0797556ff68bf26b46bb4538af88e3c9b769798e768d2d30cdad1e7fab134e5725bf3985faf351741b9d8b9d0bef4d0004df7d6294ae4e0e3628b78e6e979374856f1e312afaa740eaa071889189b42e25285eb8de74a3f41a89786c502a17cfab1ac24cd17c16275f7318a89b942aee2897ae4a963e3f7276a91e4755670bd8667ddd18765c329da6d6f028c1ddcfc777662fa505ea10ff66ba8bf6756985899598a04853a7d1dfd9b593b8345aa980b6d8527684d3a99aa6aa70d0ec83d6bb3844a08bc71885ea4db336d4de1f267b639970923ccbadbf2ceac2f4a1c5133e7a69398acc8a8ad570e72a9c4feb69281e383b0e589037597dc628bb3ff28645444f9451abe470bca7af87e55e57bb26db2a777305fb979b9d61ceaa3bd5fe33c027b82b639dacd1137f7b68e7f1dfa2dfc94447e7ebe593a21d87a665fad1536910501228f3965496edec5ae41188846656ffc609fe25efcddb615e774feaa2e95e0bc2e95e710fd9f64e1fda7cc1f12d66f3c66357d5efe5bdb9b93768bf4d7a866208ab8c1ab1dfdfd4178d05d05fe65862d57b21c8a98e8b334bcbcc51cb8d1c6cb1a2f6946a894c966c7bbc2f61617d8e19cbf49e1bf4443ff1e16bc6fd63954e8708bc5adf93bf2a814f4b9eb09ae95b1db0a18ef947fff8084678ca797e938698b97da75d9b4efe02320d46fa79ed762dcb5c2f63874d4fa8b70c69c8274cbfc10be70ed4070aff105b192679497ca218271c486896e8cba8870c49cd5598b9b0770d781946c61658893ca7edce98268888dcc44d5a8c3fa253457d7f0fb53a3dbf854aff7e05466de88e9541cb0edaf107c969cc236c096ddb73a1614b0ddee6882fca7e94c7cf0f87ec77b95dac39304e7ddf868b9ef3b0d527cf1f8b3f63af4971602cc6d44cb67f37a61b26496efa606a8cea887464eb896f2c4339ab424a28e31c9689bfccfe9747ca651bb937bc8dad593aa8ccb12dcdadc3beff5cd12d1dac49338afddc768b1fcece9417cadf8c9f66cf4d21643cc6a448267b07a7bb23ed5f5bb7ee3efa806abceac870ec295e620a4b4e2a15534f9b0e0be31bcf75e40847a0c9a2ff83226fa2e9de3f39c27dde8f115da91e19f63665f834a27a292c9d39ed86b31a2f15d9aede41ffb99c64b36b1970707ec735f38273e9008bc32c1a871891935c4d3e3e920a87edcef97069d154966fbfaf1ad090a34b7b0b1be6fbc68ab4309907ceffcb2e9697c44cafb961289da8993675a8082dfd0178eea302fb62462e91d885c1ac805f385c1ac49a7dad27b12c795e020b8b4f3a15634f8b0ecbe3cbce75e5c846c0c9e2fb7326afa3b9db3f3ae27c3e8f715ce91f39f7266448305278d9281d383d82831a1f10a9abfe45afb8cc632f2ef84069bdfe1547cf7f8ba3989880f10200cf22fc83254b83b9bd5bbdfe18659fd15cb91ba9f37665e835127b89296d3dcd86931faf10f9ac9e4170f1f7e30eb92048fa7a2123f231a612d47c9a0a8710496f9110b842a3aef593fc04a12f139f3cbc4c493d7beaa5729685df2785a97f59c4058efd39092f59f4ac7d0be72e1f6ad722e1b7836a464526f77a6e92e38d6445881e42b7b8b02b14aa3d6716c4ef83b70721a08848cafcd66e00e8842cf5b361a416208faa0d60a867071f1e2792e7686f472e89e408ba09f2493dc61714b983cb9aa18ecab5693cb5d7406b7446bd9baf07f3f0ea6472f61b2f4fe441b772e56f96bbe7b4841ea0ab09e311e0fc12c12a5dd2500c7a115cda162bd224eb3a0ab9ae86811b037939adb2f109e79f245b4e24fe120db93f05ea8319cb624714fc9b861e01c5a9d8eb45e9a84392597f3740ea193b8b8721e77e0d11ac4279b472734c3288faa274b2306e9707adb939bb35c35911a74722b89db3718fd0a522bb6365b1b024c51f5fc53ef437474bd17c09051e0b7976a1b8e365b3303bae9745240e3ef9cff45fef7afa471a9df160bf7af3cd950ec170cfd127a91f01e71f37fb93058dd425ba61a60161054d7586d70db7023a325fa93e0015e9da4256e59ee5fe6dc77e14be1fbd60017073842d62c538aa3777d62f1dd00e98eb5526deaec5e0ba8f1115155ec8f8b927c07337074e69b0889c6041727fe34d78fd9e43e0f73e9c5fb0765e4274f45bc2cd9263c62aff4a02f58eb1bf3f28855240446a8862a4b41f593665ff5af6a6abbdb376a9db631f865c12f3306bb79f32c1cc8c79d428f1284aa62f314bb98eb164396f176bbbbf310a2680885d070f5bebbdaf318bb58f4a2bdc5f3e1b93c18236a0a9c5b1382f0317313f41c280b485d5d17f134638a3737bc10e0f1a75e139c168b0f6663b9849f1a3021e885526c33ba24e0d66de7d80269314b2038ba2a76401bdef0c9b07077f86bfab7b832f1cc72906d45572682d9e063f37462a247280d3941b501c240dc24460cfdbaeb54525cd119f56ec4825807e964524c49e6fd56e9cd43a1df6126b8ed3a0001662ffb093616fd1c4608f59666cf2725bca09f8bfb92b50b3bda7e509e170fd386e025dbbb2bb605344ffbeb6e1a52a1e1966e5b3393a142f016f301111d67b935611c423893bdb8533d952af0e8fbfbdc157650354e23aff12b6fd3a614fd867709f9777a0c45a6344e3d8ea131f08122c59f321325c1cc7e6d65afd172344223c29ff223d09f870aa29d73306751cf624936ff13f0a9d39b95fd276709a00143f17113faf1510bef8b3d52a1b411a93e4b7c9737317708d84d45900a18d65f62481c543248102a898e9f6e424bf45ea9eb9952383383d0d98f78376a089cc8736c714f92547dfadc172c530a4074038bda0c1e17ea9d97339a0f51359122d13bf19e686353dcdc93d42f9d8aee5425702ddfc218e021aff7aa3200357273a1f79eefcf59defd87e9d579c4a1f0197657f0adb9967a4d297d95ebf665123e06baf164f2aa92d4b8dc189f5a69724da494169f918f4e274638951cf80f316b697893aeb8feb2ccc918390d4b9af04b763f52f3f4304f26eb09f22a1d72d827dbb45667b447f1a5bab9f1a1b9b04a1c53c76a3b737e5c151b34c323a77cd19ffd93f371397f4a779a8b231e3aba4af650a6101c616370c12ae24bb014463777aff71efba1e7667eda1d97656b676a2f93db61fda9081ffbd7481aa3297395d92f65512daff59279fa923869527df37aa1fd819c03e1cb80537d427e9f8a4a3a387ae39f9f138f541f301d775403b625c77c0e378c92e25269e32353502318037208012c2e2d75a0b9b24a1c45bcf13d3937a41adf0250273600a524dde56e460031dd07e669fe5e0006bf3f70e252a076381a9fde46d00cbce3f47251a78268a10a027a222120d6b3dcf1f8780a3904a9e7e488af9d6aa45eee1dff10baeb545e00e23e06a8f43d3a785567d66aa258d3c4737350e34a3352c8eb21545082796d8a77f5250b1520da5f975af811f783d60d83680ee9fd2b96dba74590e9e9458b35952651ea86ee5e45e92f4b381c77ddf4376fdbac939eb82215c7e99a93a3078bbf9a79fbaead3a63407915ba9d89246be740dbac9d67dbb7a69fcfe7a98fe7a19b9a78e17c525862953274664b3e00b0495210f208af69f8a532db98910a745217e3909dab055517b167a06ce19eea76b19e80b9a06ad58fe19da4681ccfd59417f8ae611876d01f184aadb7f175182707e79566854f624623b05fefd5d7a14548fb04cb51b1f5fb26863848e728c29e38c922f1aad909721d2c53a0ca0f70dafc27092d7e4f156217f3c8a98945900b81486c6258f59560aa05d8e1e73f31aa502663e3f050a0fe398ed39ae70262e1d87d53a7489fc21b2a2fdbaa91fd03f541f3991601fdfcd31bb7b0d2514a2810aebfba6a5c77de2b497d6152df2b521e220ae28b56eedb929b88afb53e9f6139564590ea1c58dbe99a78e5725926ae32706938321827c98b5af201e2ff20bb1831f8ac3f95335361de26afd131d874c2281caf8b9a27d01e2df6896ef2a31af147376e307e548a61528604222f0655ebb7667461b82e78324edfbae872f546233b045a6df7da00955e3f52109a687772bb881703cb14a0eb749df18f9487687deac55c16e020c72f48e539b451df7857b20eaf2b9a897d4a27ff069e503a128bd657eec8247f161f8228dba94ffd808a876cd303c99c052a64ccd4b0a117949a9233505e719ec342d49e22939f76dc17e31a05078279db8a41bf21d5193f2a57e5125fefb6774d72938668796639bb60a9fb1c87410d87334826060a0a51b03652647ac3c4010a4a9b0a7476180871e2204a247e4e1c31280401cc6e489ec524514a288b1fee7d2423832cd1c29cc6022d9f1a632d04347aae82f6657fdf13bde9895a285cf61932751e9b714b1c22194178b8a50979b9b2e8dd70e6fa9ad3898bf4ecfb89b0d3849eabd8d672768a3d1f9f8662b59a258b6c375a0aee95b9ce5b5ef09da787f162b148900880563917f02787223a34495b1e20b8d0b9a9e19786611f7d6c6107895e01018e7182bb726c0277c151562f526c6d26081ad410e7f2411ab4181c4f304836d8d5716ec28b0467c97d30772a7e9cb6256858fdaf1d9ab05af99bb278a01c76d38e74ab99f0a452c2d393af8f1ba96ed5c388d152b3e89dee3ece9e127db9f7ba5511410a2e17c05fef8c52d47313c2ca6e59ffdb434104d01d19773a6617e291eb880cd3a4e6fedb424462d3a51aff895b4efd9fa59c52dcdc9ad4c96ef0d64c60f2727951a625d9e6add7a2fa561dd39c16083633d99f8790456bc92c19031fef4e7297b56b5323f9abc64ebc6be41f68c4df749e61d09f3195f268f32bbf9c468a270043ec9f40c3c74b0224063b14755ae7d5a94b594eeaa27342e3e61dca4c667ce82f42690a4f1f0245e1a35ee06717e5b863ba9aee4b6efceebed3d5e62b32c614bf3072dd272726256e5007b8061205b9987325b8674dff063cbabb0e89e61699099077d219b98989425949b8601abbbc68f16008891010d35e5e58246550f3901dec9d5649424d36eb14300637d01340736c6bd3d5bc0cd39a1a0270e1e0752479c96e7b66726cbb76f1730c73049d5be988ecbb6e726de4f1eab24a25a0e17c7ff23eda37f638f5f28b02218c652370325ce2073467fc06809a312c336d0a9acef6b8f2f09d4deb29a4a61001754635284866319c8bee508ff69e78f0706519291bbd2316111b2181042bbbf639edbaec9997515ff1f5d3ca690c4ce6f1d5d6922b063ca00f345e38211c7079e9a9492ae05a162da92605b2dccac3280894b6223424b85ba74fae4217f9c57d509f1a6269fdada242652547930ac61872610a8a836f15c3a34df012f79c7dc8e754296c5c2806929542cef07266a71a0fff247df2763932d59c688b88593a697321adf78b8c2bebc1b81ac32f9a7043aa9a7404dd368e8be911917b1f77b9de2177d18ebcd39e6eb8a2baf58a9e87b2decf88eb449b21eac34ea1aa1a9cd7f02576c72a09f8e712217536688d4268211c43640d924ec08b9fefda21149f9ae80f2be11a1ac72d88748c9f8a6b61bae5a99e05f29fcd6c9d8fcb298b4d9ac722d89f17332aa482d17964ed2a0f75c10915bdf72b30b9d94e53d78a0f4af05ffe102a2969726305898d2e000870028c03d2dc48808086b563811c5fe1dd639c1e892f06e1aa0948beabf7c742339f9962b98d2768d8dcd7a0576e256b2033541db2fd3e931d77b9ad8bee4adbecd295ea34ca018946f4ec523d05ab22c51f962f78adc1100256b9649aba6130f0c34de8e8e2f2bcbfdf78505ab0fc84a355d3766f784a6d189e3c8d8f9f14646a8763ab6a36016c5206ed7a28273a66498d714a5cab1071ebc85e080066daa094cd5bf47c75c4f3fe6fee57f2f9f2a840b601ef507396621827972219a20f2dd4beb9cc584fba50103a12020434d92336fb115048c4dde5b64ef93207ec4b7e1d405145f3e111d7892005d2e3cce03c1bcbb84b7a10de2b4c2c39374c85e762416604626c7891fb5079e68e26e2df48b4de14d40f9c6a8bcd60417b9d8d32485835e76b387c4390009f7488ff175e0325c5538cc7fad1adf046b9a0a109aea1222a747517f4ad9f80f7a0005928094a93a6908eaa9f688bbfe496e582b0f963a4fc9fbd44e4d1a60447b9ef20714deadb3abb5e480a7464b19cc1ce511a26dec19e1473980bbaa850f15d21586cdc5a92c60ae620c4210a5457303a11279a6b044748efd6c701325e1755d0f02ec1ba6af90e094286d1a37b35f1bf323c3aae6922dd04487599d09bc6ba4d929eac2df117f2b6ab2f51dd0a172cf12ba49223c244597277d47ac083fc1cef69c686327b9e56ee4ec6c227d39e4800583e08b8287590e9c9e1262265c7382678f3e7c07a54eaef5560d9241efb07631b80f92a56e43aed34762a3213f596747272afd5000db82c0d2903324fb113f550b0c0268c1783e838884ce398864832b021bc38ece85fce9e8bf932855ef3d199ca4c8a58275832c59f1ed6a2e632cc258d89c384743fc1cb338c1293387f0ace070153307001830ec7b82e99e3037b329f01da88e6af9d97c47c0477c47b8daf65eb49f01c57331bb1d38f1f888703593e6ff7f130f199f7625c8800f0069b1a4a926af266ed51eefda9348193e3344e91ca4d93a802eb44e0f5db879c40e847c023a41625c95cf50817ef4d77619360603aba4d564f104d253123df9e78d3d2782a88aff8068e07d5e0f1e465b64d9152a5f907ffff311c76ba721d33ca1679f38b16451c70f33a054c74c76f3b707265dee032ec5e8a42657dc1fc801147602d5fd4557601323282c784b146d47ca333d3a41a3d2587e682a3c40d9f44f6836380d9549d52e9eb29dba4499f40c08369028a8f7538636bc763b084fc0185a377f4faca27b900a4d5e0f0a2668b97509f53cb0ddcb8f75a71f930908d3a7834e55a60803c39f8698e97acbbea9043797cc4f7faf181932976d2a970a5db4b49fec5e3186da59d0c83a6766c9b44359bf82dc66ae7b935d072e16b0dc4bc46ab3842af609f9dd1ea629ee995d959f2e82702898d3f0700bfa6c823b998c78e96cf59e9db2da0cb5ce6a58910dc38d4798ee96ac1fdbab11166cfe23382527271ae65e0e6fbe1269509d19cdef5c068e4c9416abd76f443f11257f2f7024be64a5c00f24289014aaac2d060a4cdd9ef481f02b3923649f419261030a93e00bef26abc3eb15e23355189f461914ac1d2f01207e72eb668700824063258deba46f468b9720b5a022a116a194ed85d0cf6f25e732f10afda7ef81c14b7f15a6b7e7289f488403187353c24c970ebdb518b3cff34bd1947154aebfc508b7c0f44307046e1403a7e41336d05398b0c9a70f81e5e3a4041e5da72cf0ef942696f69339367af3038fc44ab5d55120d545602307255818e438d4b76938606882455fb6ae1d4c5d40a2e59cfa82463946e3043244b9859706d45130cbae6d213705654039b35032800f137a9572a2976799cbf06f44639266b9f608f205c60e25ff3395ae99e648d5856b9386f4205eb54420903a81c0c6f9124a1d5e0fb24464076105b7275f5fd9eebbf0e28cd2c081ee916e2b89ff091bd261a2697315a793f76bf72f75e5b8e00f2408b5c0f6e314dfdbada5454f38ba19689e9654a539f7e4f17666d393a227076609c9201db3f2ad05ee84cc865c24898dae3befc3837adc761560b9a74f80e78db2530e42b2c4e75969dc89d5b3e6a2f41079c0be1a149bb732092df06ebb2a70483896ed910a28b5d161cfd67891bfd275e1b8163a22bad36595e7023542bbf3bab3089e4531077d173297a905b1bb100d5f272f8a7689cc23217c184e85b3e7ef917c99b59d00a9ce99ef650c8e12d36ef457a53ba9b4d501644fd53b392ecf7fb9a9ed94266bd10ae800d5461e59d79e91ff3901b1d79e7a2f3732fc2f174d22b846c019d88e8e3e8048c03389171d3a51cf56f626da4d3a10cd81a68972e6589b044908956e6bcc2b23444587efb5c4a330864e9aed2d994518948ef597e00e95972d38a10a7b8d95477f02a38d702c01702111a617dd31b1c76246733075417cac651059930ae8f14f6018930ee16171021bb137274dd883ec7a8e1a662da38245f978c5aa8f1efe9e07ad0f34f84ba499e1d7a9be7e9512bbf69e308673adf9c7cd3a31cf5a95e6a86bb691bd43f4a5acb12a7f158f12d8cb507210bc23a06aae5d0dc9b6730530803d4c9bae55dd693932f2a6cf2e0890c3ebd8bbd369c95ee79ac746d953a62502880c49fd03bc35946fc6e863eaf4558f4bb8c0267245d95fb0f60f0e65d21ef164063f156e9799b135c1a673a5ca57284ed334d7a63f1aa701c2179e558625785c251c3ded13f2cdf6900aa0243d871f2d8d81bfb382d1a2c548932cc3ef0f0aa47fb20b9dd1206fb3ebd12777650f0e378ba4dd7cd13f01188c6cd717a1db486e6f593276edf53fb1e607eff5633a064df5728c9dd2433c6f7935d745013f54da8e89f2d547b23b6b0661af10f7b61fe162324d6257299c93352e823b07a6a72960889d7da071a6d5820f319e2217eb812228fe416264476958b5e9e743852fb162c9dad25643e2d59891925cce604d48e19a91c5139b120e081eb5b50f834fdb85e89e7d9688b3e594b1943e51e15d523111550faa74476e1a00caadc064f06c290918bdabb32c9f215b1213463e9f28a06d03c21a3b09e518a4dd4f83f299e54c0d39dd17f1ab1f22d8b83531312cd48626c57205a8156dde123bb73d072752f0ff166e19a91bcc18901195e635ca9574359c6d21bafc70761ca9d6c8f24cf5ae1d089962b20157922f19f388b54dd20b1baf2a28a4dc27a725efc42324f571162aa3e3a09dbdf6459426d68a41c3726e94c65f00fb0855e72badba1e6f9e35fd4628cc2b0912dfa90dff5d24a82117ba06c211817441c4ee9e8c8599198cafb637d511a1ec1e4db620507257c88fd281703d5bae76c3fa9b647399c8af17fba7de90a59c1ab49028910d7d25c5922b95251420e1b1859dba0a72f1460a1ee485d187914a34824112dac02060853fa42daf09bdc60d0d4fa26d9df72da63ddd43014b198d018459d0b079b054408af1ac67135138898d6885bf2ec1aa9d90f54083e9d52083d2cb8821062b96774ffa52049fa5b556ef006f1f0e802ad41fb0044f0c482c169a8daa37ae0db926028d5249efb51c9083ca56213c4a768912d16c3319fd25741df70d673c28123549a664270c45032e19dd4c08de9317ff56cc382182d391e1027d3458c5b4e23f2befae1f4e7e9621bb8116bf2f60b33727e00eb94c3e5eb9c03e8337279268e94ffa0fb424728e9da5d915fd24c2d4599b493324a2099273323d9f6d2993ec199451a0a8f0fdd661626c18e3a3b64ca043fd5a2667f53aa910fc9631ffd47e7d803c5e7ca084595f132c29d2fcfe63448d1d600dc9dd4116e79a5880e14d6e5015703d71173da7e9dd2d06a74609f2d00ab01f011a6b994f1a0bae7b11af6eb5dc779b7f107d2dec1f2ba897c060635f6df0ada1ce5d96b0fd5ece9aac659fe8214dd3a1cf38b1c0c1c497111eb39381c16d86626306b91649adba5a5d4c7c1ba61d349acdfa1c4b56e65ff1a77fd11366602cb48d4b94b8a22dbfa683c571d29ff51cb3cacbbe90953e2aa1a810600f364bb665958db59fba1010819cfba6892aec6cf192b2e094808c0374bdaa350083f56c7f06e511b8f60409a3af4aff09bc80259007825429bd0e0a0c5c5a9b06c63d672bcb08dd288840fd1eae45edb3828db768d1a08d3f1d513a25225767872620befa65c40eb0f23b94ca224dd1d1c3d2593e7c0f7e612a8708d9e55bde05a020139db0ceae7ca0273354a0b20c23c9d66c32142fa72bc87c63056218303b5865ce9f166d1f55bffba7218f9c1bb4f73a4ec9dfc74fccbd505c3a9c3cb5b2f0334f2310d580858fadb34215b316f8b0c5f11f05ed94ba81b582a9320dfe8505a8e623bb5cc37e741aff166bfa02831f81a89cf994f390a1caf89ccc0c9161e9db1e9845b24e9ded6dd6e5acacd8e04fb1586726a0030e7e71a7ca24749e365825072344f6de1658e511612d79065bccaf243e03c034670aff733e24fe1f866603a382754c15e1fe9bb423926681ef2b0e500db229266833e74a9e9fda2c8a2d82a65f0aa56dfba341271ba5a6cf37026eecf4f4d08576d7ee1081e27b0d116798e8a189d52e81b2e1e94d820102094aa4bd0c2786e692886008bf0e7b0324b3fbeb4bdad23521e58f3adfa3053381323b4d279fe529cd8346c186e813a654279e663923255d6907711286d854123588e1a33492507ef5d8e2c32727e639d7289d91fe489c3d4ca4631342e2fac324f213a7be703a8f69bb843cbe4e50a424a77b8961d2872423a21ac34c646af54dd9f8e589276aeaa17c090329cc38a6d9d8e4c5af0fe5526aad436c3e0241a396fd4baf393ac2753b266be125b4a2ae1ce4fcb1e000edb26000a5399de8eea2538fd3f461bb553899d95285b6f6e2639937e5303e89453cb233990f06c6831c33249f231426cd3a21c37894b91cc2259576e22b7f3585fd555d71844a016b63bc172d8e92c6e539123812e7593b07ba523d7011f15bef97e09dd5e8a98f10153bc3bf9310795e1e9e1a709901628da6893b406e9ebf6a94c6c7f10e810f29917ec9d53ef6877d05a36031037954c29ef7689da6080ec032023a32294906f0d658472dbe58295ea69054fcf44490245b4d17a857a191efa68019cce32c028d6ebdb1a8d911c77ba7abac4d2e239b59ee1a3fdb9ef8aacecb8e7e3e66c9f4353c27e96a2571ac0c5e820674433e67e00422885726ca9905e58f257e1541c91fd8e0ce22b6354f504a0cb6a38b9c4f783918d90fa7619760c31f09a52b9423edd241e26dd2138c5d77e3b83e361aedc5308f16e93b968dfa2e7a32c5fd406fb0363f0b689f8442051ef567303e9e0ee03334f27f179559f03eb00a2a13319da97ed62d6f58a2c5cd92761873a6042458b8ac91032ae52ff74f3706f607a4125000a13fed0c2d89afe1260230d32e3fbc000cafa706912ea97e9f09cd3799a1e03ccbb00c4f4aa26b42bd6bfea08f087e8a579eeb97eea6a7ee02a3791d6ba774264a33ad83e1c551190ac89c66172ae9b62829ffaf3472b7d8b0c82fa609904238810d5fbe3c885b9207128baf82cb5b82c41ca17e1e7745fee4c89af9df3cc01c31862508ab237780a145761d91c36692ade1030abb14d5aca61771059da025e211ba911e3e16ff01b5904b8893efb0760913f20d78221dd291901d204af9c0723119f58c39515e7f0999aca225bebd30cba84c8622135d8261c6e105f18e7229633c1a14219cfbee9e679e6922ba4da3e246edba540c4e295eecb7005c2725261f075b9e3fd8950be48267c7adb368f0a5f9b50d44bf7afdc91ba7f2ac6b5005b846751e8ca0014b5552417dbca2e739b92226c7a17c09261e855a1a7f34249649022644e54360caa9997f93e5d7a48521c5d1359a4c222a2dd3415c1c8a618b385a2bb6fce92a892d9b0c973e834da60e83fbd79dcad9c1b01acdb934b5fb96c711a2276e023e9990d459949e0371759e10a4def688963b023a02f7c957243e85c7eaf581c5c25615a9dbd2323b92e842934df238ded4de9d99da5a3f052f996c6eff2094152a00819458bc2c52500e9e289c6dcc218b9ebb99993e3b4cc5e0a1bf6724aec50b9a4d0258a7af4e0508ae09c9ac3f6c358a5bb886dc1307d5240f1b868e9657edba1352fbc47284408ea4586d927e479e6261daa89c8f4e9fa8bfec4539a8d76616b582d7ee1e0662cbcb09c8221939f92c41af59d84b18c34c61801cb2295420378ad62002df09cd5b65935886ae9f79f8bf350c4101765f3f0759fde453a3d26ff81b5dd201c26e51913c7a1f3721e938292f6885b1024a1c816c53a66983d6130727cf6136220dde3921d4190480cda6d37ec6c95ee28dd2019f410caf12002eb9ea9305b1776afff795a995ed1e9ac9b381a67122f02671a2f0a67e22ff267ea2ffa67f22fe267fa2fea67c22fb068872022691721e069d521ae692f221d6a7b24506c8b0c0ccc55b1414c5958481d5c9749936b005d8c5e28e860402b0863bd2b186a4324bfcb8b14894f232827608b9477b7a0b8'
#data_string = '5036187647a21889fa5d1e12d6615c8ea0623a565b60149f1a8e1e471479b89d409f9877506c1a7a74460377b9661b7a1e02d37077e81ed83796f016a72e1a59b812f7521337e83e3f8b529954383056bc825d1a1d02c49a1e64f09d1026549b7428184a1f30c0611262e79fef6367806fa5bcdd7fcb556510f48f569c5dcc79d5fd2ef15f87bc8a1cdf2605b6775d048d5ac6ac2286e2481bd8ec2b50f8e85d4c825f21e4c5f30012fd31f395d92876562f7a4b1c09e5d519dbaf7f9b5ecb86173ed888a272e7e26fb7d0c8529b490a40434ff874b4bf14a7bc9a2f51a9aedc7268c6d775b451cea62aa18018dae31c5138e796ac9d086f78ac2777e0e12201004556b1a0e782098d3a1aa74ff75625b0fa38fd29e35452519e086f535bbf2a0b8492f2efea882f60af0e198e5c9bf4f88b6a9068e2f9cf4afba3ca0c9fe759466a8bb32e09045693ca9dd7279f2e2b05019394d32f3570d1e189d741bc66764885395cd13ccdee49ed8bcb9e1e2f23754ba9ae7338f9b812bbd727261fbb47d15a38fc2940fa0bc7795f1eea9d8805c05857c3828f8b04dd774a53784d8b37f471800be75741179839dc109539e245d257a06fd483e0c035cca5c4d4e5e772ad2d0f31476f223754f28ead67bf3f9bba345242758e0ee22d8747ad08abc5e346580ef3b4ebb43a13e826208febcc5f2fefe2e8d3a999d2c02e7bd24e7d7ee4fc620016d26e14229bdc97827e212fd144328014d2e4fc7eedadc5e3936d3d8c50751489a06f0eaa071889189b42e25285eb8de74a3f41a89786c502a17cfab1ac24cd17c19ce7c00ae3018532f0eb8cf5f36cbbf5ed2c5de0ddfd87a4d123b3a9db3dbea49f33abe3de13f5d8f99056d5053f99f0fa35ceafd83e84ebb214b8b9a000e3f3ed2efd35066b8308d131a134db33a7cc3efc5accc677057cf50185c9ee42bdc8852eb4c2ef90567cd3158febcc16bde1c516c5e4d726faa4e87da28ecf3bbf93c93dbe8ec323b3dca9188a9df316440a12a4f7ce2a215806caf5a4d62f1f85d7e5eec51edd2aa6d6fc6c88ef432f9e22e686abe4c2385fc6ba17536485069914ce059261f096a80ee118b1ae7c9ac744ce99f3b2a57cf13a4fbb8c17bb7d0309ad90ad98aabcc44859bfc2615eacf4ab76c36caefd31230042b9f75abbe7213de3799ec1ad0abaaa9d32f0e177abe36f7ed9f03d4238a9ce7395c5cf718b3d92792716c40994e83f622aee184ae91bbe7fe0ab2f42d04cd14dc210cd2e3509b58f112fcb51e2894279cd332059728de27eef1946dc757ffb90021cf465c04aeccf7b7905f5ba73fe2ddf1d6b5fe6c2ee9ad7392840d3aad884e8efc5b1ca88af6c0ff9fa50f1ddd91a1e3a62cb3feb989090a45cca043bc349c80394950d5e798b091e9c9370cd468a0cf143081967e8c8efceafb2db23d987999a1063c9a3a9314e21b89b3e760be3f3424808282e34e918fd106ef59e4c5b10ffd5a2e689afefabc3426218fbed8abf5efd726c09118bdc4506e94070532224a0a31a1b6c00e9506edb323875c5f1423fdb569275e5dde06102d81d6348ebc8b7b26719b461a2b4ae10d82803a031424fe79eb9025780cc9fdf6318760ee95e52486daf7a18f2f46a4ce91cfee25b46ddb91ee7f5092714fbe0001bd802d7d0170022192e1a9ec064d03f4587d5aea99e1b6ce1c9db6419b006ebea79e72c1ef7929a437601e95266d5ab6c67db1814752d6a93044461a6eccc91bcf5924a4194b13c4efbe696213ddb5c9d895fe6a7378a129b09b8628c7ce23849315c615d7eddeff8600a33e7e3a4e132f3c642f1ae62081929bb9af4a613b4281c50425a14923b9db65fe7be0e003593dd11c7821ad99c9b49501649dbf93c49034ec1477dd3a21ad6094029a4bb6b3d70211d91b7101df1a20a334a26afd78236f689f40625326874667bb39dfa3d9bb1448b5c52083c932358494e427a88b80f1a2c1cfd66616d7eaf523d5d09b249ffa0e1d87edb3c1cf5bb6ac99ddb5c0d36fd324b21798be81f093d41a1b8654d0a3b3d462d99a01076069d8c07ed62670cd99c29bfa783b2889017e3fded9e496f25d4c0f6b3611a624f89150c409381fddd1e384e3ce8047050b89e6a46eae07eb3841a56187cd7141c122869a440d88db2b997060ea1eec8bc617cc088cfe1772aa114db8a78ecccfed4408caf7003d7f02e90cd9b6d99522449f8d81fe8b77f11c5cce0592f8043daa63e10588c235407eae579481c318b274cff233358e11f573300f8f7d42f3eba3c0b49ce1af1c46c86b390275a26d89854fbc68edd84c12287f142d387c9ea2d68b8826f3c66357d5efe5bdb9b93768bf4d7a866208ab8c1ab1dfdfd4178d05d05fe65862d57b21c8a98e8b334bcbcc51cb8d1c6cb1a2f6946a894c966c7bbc2f61617d8e19cbf49e1bf4443ff1e16bc6fd63954e8708bc5adf93bf2a814f4b9eb09ae95b1db0a18ef947fff8084678ca797e938698b97da75d9b4efe02320d46fa79ed762dcb5c2f63874d4fa8b70c69c8274cbfc10be70ed4070aff105b192679497ca218271c486896e8cba8870c49cd5598b9b0770d781946c61658893ca7edce98268888dcc44d5a8c3fa253457d7f0fb53a3dbf854aff7e05466de88e9541cb0edaf107c969cc236c096ddb73a1614b0ddee6882fca7e94c7cf0f87ec77b95dac39304e7ddf868b9ef3b0d527cf1f8b3f63af4971602cc6d44cb67f37a61b26496efa606a8cea887464eb896f2c4339ab424a28e31c9689bfccfe9747ca651bb937bc8dad593aa8ccb12dcdadc3beff5cd12d1dac49338afddc768b1fcece9417cadf8c9f66cf4d21643cc6a448267b07a7bb23ed5f5bb7ee3efa806abceac870ec295e620a4b4e2a15534f9b0e0be31bcf75e40847a0c9a2ff83226fa2e9de3f39c27dde8f115da91e19f63665f834a27a292c9d39ed86b31a2f15d9aede41ffb99c64b36b1970707ec735f38273e9008bc32c1a871891935c4d3e3e920a87edcef97069d154966fbfaf1ad090a34b7b0b1be6fbc68ab4309907ceffcb2e9697c44cafb961289da8993675a8082dfd0178eea302fb62462e91d885c1ac805f385c1ac49a7dad27b12c795e020b8b4f3a15634f8b0ecbe3cbce75e5c846c0c9e2fb7326afa3b9db3f3ae27c3e8f715ce91f39f7266448305278d9281d383d82831a1f10a9abfe45afb8cc632f2ef84069bdfe1547cf7f8ba3989880f10200cf22fc83254b83b9bd5bbdfe18659fd15cb91ba9f37665e835127b89296d3dcd86931faf10f9ac9e4170f1f7e30eb92048fa7a2123f231a612d47c9a0a8710496f9030b842a3aef593fc04a12f139f3cbc7c493b7c5ae546c474e6f88167ca58ff2666a95bdb6a08ff16cf5aad054d38cc3541c611610961e3c4945dc87080aac2a7eb39e455db978df6c91ac1f4a7c825556406066a2bed5a340d274e664fdacd641ce785b908ff0822071ecc6462f98aea4b2089b484fc07a1ddac8427079f576a4ca089ba8f8e359476293cb5d7406b7446bd9baf07f3f0ea6472f61b2f4fe441b772e56f96bbe7b4841ea0ab09e311e0fc12c12a5dd2500c7a115cda162bd224eb3a0ab9ae86811b032e1bed92e3c7e18e1f45e18e95452608a154663a20369944adbba7062f02a1935c79e70fbc19e6ef1528fd4a26c61ef8ae9cf5a9a0c89c39c162e189dd703a08913cab83e59b50863382993b0e0bdb86610549f2b84a55dae383818a6b546086ae81e4092686e0a2360561136592011ff284635f01c53cf2a59e2a85e54fd007a51f592725d45b42f93741de9501611e9cc9d472392771def517474bd17c098e9d94592e9c8b7926a1ba73627215725819984bacd3f90d198de1f8fed6c63d19846b776de6d6e19e95846e1e10eaf5477f37db97c22701c5bbb67246ba0546ac16d7e1de9183b6ba06de418e98b6b712a9da4256f41675fe632749d7895fd6e72da2c55a2e589af466a4a528c3867b96e59bfba7c43fbfbcc16ada009ed366828d5aebd7671921722357e998042b663b0a174e47805ff3446301e70d75330f433a350d4220b3fac3b5150e8182b3fdb95952157d2eafa631bd03adb92e723172a1e1611e54ae551bf32a05c923c41209ddfc138a4377f335a0b8e5810de3f472eeb304196d48fa4ea198508634b584245f4b804b5edadbd01f445bc5ceb1841963a80bd5cf478bc24f4f8a45fed9b4991f176bc34f498bd32ec82508edc1c669f0257e8e63535b0718b580189568f3932337b314c51887956f0017189468ad795247da1640a9f0b030b9a5e93e667b9053a57211646b42116412d610c3806dba9690563ab6c0f5ba49bdbda1619323d112679dc6274987d35045782395fafea5da877bb602ab6a36a48a6a80e3c2ea8696c5230dd6452382a9bb2602347370e2344b5af921bdc0692890f11e1207338933d9e8872f23ae55a58c151163732db618c7e85f807b811e3e863cd7df00f7d62ee26246dd20493661b2c21e1237625b4f3751050e70bba52f24e0a2258fc9718f13e184264332ec4e56a503374522d22c1dd48936d0fd3c3ba780062d79af6106b7337f695cf480ae91ca963cf9e2111a2647b78d69ea052180cfedc15c511fb8aa61890102c889d8e3041bd52a58c719c4244008e562254171201e48ed750fab1485a9325c120170d427cec7d14df20cf22ee6c86277a57898250720be36421800c40baf0217f0647f027678d7c47a32b75026c2c31a1f45354dc1df84b0a68dff07dd11976a1137a752a2795375499085e364a8bdc5ec27032753218d608224b9aa6369678ec91cb750a49ecf6eec9163d5873f2da6216106c5947b3cdbfbde92e528e8e9f9b0ddb7a562a5838b890e266b98a8877ca77c586b0ff61bbb867804d59e9059a58aaf90da89d8da8bd5a21a163ab5cfd90919e6631ed41286ba117e2938a054532eac339a243190d5ed7be7185e3c436852b864ed285d384906210b8b9ec999824e0a774d04f7e9fb68c5047ea74813427731459bc7f7818aa7ae89eac4c3572209af0273242436c9f2f93b00708ce76a3f7563c9bf77b1412d50a0d6288ce9d2088cf9f3537a275c4f7b858b04b48bb1c7e7a6a07fd30b7b95e2a9d58d34c8c44b0094c451922f53446287615558a77ea145968315fb25eff946ac551515ad531b27b45a1e79ed708cdc3800dd192b5af25b9aabb22bf89086aa25918efb1095787ebe77a1e1c8feb65c62a14e9db89c7ec084722ab300203d581a0a0f51414d125c679d92b3981f74a198e9f8aae4749689525410080c4c44ff98539672911f8168fc0e120ca9f7c3e9af76e471837501735cc4962a5390fa9f0a0bfaa6507a7523e3b45b1f1441055e9f9f6e1485e80b153b0ca71566700d41339b82f3b28bab15ef2d7fc76f1f142a69fc652cb7c0b224b3ed18e28002972c1cc4a6ee584d1a36289c3f4f94c18ef545270d81c77a27c176c54e93a78b8366b37e82f70e5e94157d26c2acbaeb9cc2363dbe1107440351ce6a9eb9b33ed6ddff53b4e59abd972f43fa0c177f22cf29c510ed8f24b001112acbd0d581fbaa6af2d939ac4f3393b0c561551e730ea279501512690cfa3756237dab4f0417384f2e5c12792865f8ad30db88a0a9179b787f71a005d871962a4bb5fd4e7f290231733ae2a9d8024695025061537a3418a74d8f237f236ba2af12633dbb029b33aef2993db046605344fb91b377c27db8e79e4302ac4acd9a2b3cc2c2a953b10272a891de7d85cd1ad14f753eb939949206506c5a3acc5414532771418383adb80f04b4b706a9eeb949bbee513ad72faf365369c7396dcf05a984e6c09f2d72a6255fb256691330859df79dde21c12c94c4d2611d31cf4f29485ea153226863848f0ec7b8cb4fcc60040f2dd311c7592eb5d26e8861fd4a904594f566d9d3120ea86b7d48d6ac7d3a49ded5c8aa25c1301cb1e9e9a715a1d3bd58eaf163689982a7bbe18e1d97a1961a807ce723827d631d9f74a320a75c102a83e8b1472c94959337914bdf373cc7c54fb158a227e97d1440a6a1e189e4ed0b8b38e8b758e7ba55015a820de72d1bcb8d569c396b7da33d5db70a269ccea7d1898468be6dfea69ba8bc5e3799d2e8a8e3498608c4e19ef4e751861cf11a2b4169cc6224e66999dac08408a911caed34a15c6325a5d4249366d7637403a33e4a479d3a01d04104668a318ce509670e6e855aadcae7d79ad96fb5f515e10d2213157d68c2cf466881a9dc603701c18a8b308bda67acee2063123bcfcf0bd3c9a742714e966d3b91e282bb0c8d0c53475fc5f7f11552ebe03abc41d328086c6741b3bf2105a2db8f4bbab70c1b0dc73b28a9c8795b35aa07e35e4ef0be97c205a26f3b98a2037d05c6ac261c1189825e933c91b073ce4db9a9b0470601b6f4b0617fb47722bad3738661018ef5d3611da0a5115e8d38a62082839234a183c307152a2d530606e3fc8e8451852c2f7af62785ec11c3f30c1163aac9826c4f76e093061e48ae3c38420559f24d9e7b56bbd64ecd0dcca641009f1e852d0a569b991f2f832111b80e6695a6d3be1eb3033257e064823a1040c2478e088754f16a408341fbaecb999aae4b0dce9c9ade796e494f49269f788f39f7f47b9727f816e8dd73d3ff5aaae18bd399f8407ebd66597df7679dc4911bb8a64f499429b2e798128146895db6807363325af744f9d333914809a746e026330f25c1f477ff5ba60f33c1bb17c1b7a8c0232da9951fd8507f1c6ea279c89256419e8f68972f4713b13ea74cad4d7c88978eb693f592a0f3c4542da2ff16db91d9d0dd1fc679c40cd4dd950fb951ee1b04d045063cfc4bad994df1512d83e83f2f08ea993f0561311913a99611165e94c17c05f9dd985b9edaaffded3d7cfd01d1977ab0c82f15ff6d937d3a5e63ed3a51afededdaadc15a9a0589f26910b37b2f3f9e1083ec9918f1ce4e14713f6a655f096299d6c0511e1e7782e0ff5d3aec2aa257785833851174237dd251c6bca6c8f5323f88268808a945f54335f7c2aca8fc6dd8dd0c763a2e44dc1059077d1fb8d12ed63666a708afc60fec05604a24a4a262d059d130f6bf907121f826511e3e764cd9a667ce82f422c1104217124749bc84e7b1d79d59e25fc15b89285ab57b57ef7921a5f14bf5a2b11578a035dc2c21fbbd9459f1163cf27b8be96dce9b90bd215c2e2daba147aeb78aeabd85fcb6dd5b3e0a3baa1f46675beecf1d0507c9994f87ef259a9aa7ef56c2936025c2ae7bfafaa430c2f8df37018fa7eff4421b79d9ee4e107574a5b150c1b11fb119cab4e26789b8f51171dfb017bf363e8881dfc475c482b372c6dcc4b0bab6c7498b331e1d5a051ba39e77d19e9d632ece1c602b9ccbfea5fe9979d39b551d0bef4b4bdc73093f0083937f5a8606d4f69f64e79b2d065f1c46fe9f376fe9b0b276017f2338cfbda37819a944792912a028b39a9189a3476e232039d058b4b37048830d73262c015d3eee0fcee6c8e784255bad2e492c75012f442f5ab4217f9ea629f64bbf06b0719e9d1ed531733fb0076b3c7f89d189e7223a9766f0cd745e72c092659938f50db0ad3661dd575d2eb7b10fb03d2246ec7eb45c10251c33d193a251fc7db5a4c7932b1ffe7dc3adf1a2a473c104bf14efa5246344d63623419ef7642d99055ded13ef4e171d1f4e900891ad432b86f0211bc9d985ac6c7fe2f8c489f43e7a9c57d70d78e00160948bab2f12704891c73fab6439d946477db872a9eacfed0be53c1f08452c3ce68ffce5d1a460b52f686235ae80d18ecfb19fe3f8872ef224d259251a16ddd0e3cbe888820e5ddf3a2dec151d8c6aa6ff0cb56cbe861fbf2d42fa13c1bdcd792b24b50b00179de2f64d4ced12b75138100f7a15677fc68eaf152cb2692105c279c925fe60f75c1ceea1fb298d79ee17deb00b22954d50b4b8089c7bc1644d4caf2e1d1ffb6c4d5be773c82a8e83548e3a2e9107869185d737adb1b12bb25f4604617750ab8d8a37718f276f83cfd15c291f37bc0c36bb8129ac0d977a2b7b8c7b379aef806b6b8003924d1d9c5368f8b5776d924f3eb7a27a259da3c1cfecdd1aa4fd7db30e7256a32c4d564c2b7e46719aea0ec3cf5fca77a5719022d26d4b9c236d68b3646bb64f14016b6817697e788b4aa2f3d057511def3c430f02793931e76f4c98371388a338313d4b13ada314afbc5afb53a94955e675ff5a3557472f1b6bff502411c4660ff0da25cc0d90aed6840ef5cf7af409b60d69d05fd9042523ec4732ba40fe7018697269aa9bde50f46adf5ee78d3d3bf23cdea562fddf17c756af79355cccf1ae718678851f9fafa9f961a243651b647399c48f1a031469b3203ef80b4e979ceff114cb87c62761d35ead16f73ff014a4051acf3d813d36afddd5e8affd8e7789faa6a901453ebdbdbd6ff06c5cdfa7e25dde2b93e046d197432b492bbbedec70bf4626c78db2790375fd4d7ffd4ed362fd8e2894abf8c0f1e72321b7c31d51e1e04d85ac344243ae9ba02f24fd901bed396dde23ed3a20d3a538ae7e1eb0459889727228a5fe0742a686c6de61cc88000220f6837e39e39bb52caf187bb2aaab0d756836f518ac757b88b20f191dcb72da02e9fb3958d0045b9c3ebd650f951fd8027929791aba2afb8470f105de8ee54dba949ca3bddd8cfdd2fef3f2856611557269002744293fa68e8bb8c44e99c4ee2f89103a7eb55b914e31d4f9beb5da1d1d8f79eb577aa4a04e546b5b98da537d1a27b75ea79488614ba587fc161d8da1bbdb6cb5b8aad63b52aeef1b9309bcbb59051740227cff7f3f992b0e899aa9ed9dd59e1d185cc26247827c29e2f24705693c67f11a839f5f271f0e513db52b127239331e6882737da3093bee4eb2c0f6892cdaaf055f7554bfb93238f2b9538732a9138522a7b3be24d81205c2a1bbc062a1a2f5391f34f9c901996a7af1a6c572395f0486c9130512a08f2d9ad86e940341e5e47f0706ad66ade13b2e08217a135191f1977e8734d125415b7e64f32e4c183471ab42016882e2643f92ee93e70b252bb1d1a395615ef5746b1925d89508bae5e11ed727ea4f35d71cafe2166bb4559cf58ed50a9992b651c04330aaefadbdb4513b5f1a9aa6a9da45fe7dfdc33fa7f3f97b259601b2e8136258ac89f46d1a6e67b1924bddbb4f0b54f84abb91404999b8d2bdf06f595545682007b4edb6850151f5e9302694af37eb9254b4e784642709b8a3ec90201ced71861a11467fb003e9727c7e6c09d3d85e12aff3cbd72209d752633039fe2f17159da1089d25beeb015bbf154c9b55d5da104ede6b82651ac2d249b1d5628aa3bbf983bcbba959c67c7c218a2478d584ef7ca9cc206350bf23371a1b463945dfcb017d5f4d9ed28e7438a98d898125f81db8cf2e1382efcf5cb7092028e4ad01d2264177fd992f7e7099d93cdfaadf484287c4afa74a2963393025aead15e999f8dd01679b18f87f28768933376c1899a2baff0a64af66803579bb2c1ce5b59c9d20b7c09ed357e3ed58f6c17ea4281e75c7ccecdbd7143fd882e9503428afc6f085a36335fd41e36d9acd6a32061d11050f61bbd89d80136aea45189962298885f10c36112db8b1f4da51ad3b93cb19d49e8c500a28a60f5208868f215a4b12916c52e12da52ddafde902df4bd5179b4fd6345c94742f00251332cfc101900630f8bef6af730189c4088009d70f1a266d622f09fda7ffd9ec5e77df4d892f39cfe961274e469050d040b5838fa223ff005394c4841bd8b2c5088bc1640207f9950f5c376008fef1e4c62ef2b4cd64a6a2484f23eba32532e12e55c8055f638cd5afb2d9fdbb1f01b4c2ff7524ad0516e6de74e2603320453e26e1ad7a57218df883ff2fd40429c939be125300935d96d346811c0f72187dd9600e6f252e5cba2b972e069702e9136d1619de2ca8b909f00c855c0da93dfa8383ac5e2aad92fef526f3ca1f462dd9f7de3a3f297829156cf080969d986aa8ba1e769eca26d083b70ab4f9e082b4d0dd1eab9119e787e32d90708845f7355368688d83e50b51333c082549e288ba83fa0ad30a661272897b9d2f1860ab2e72600c4f17a13c943699727b82a21e85c0d1963843ef0bff24ea38b1a7410ff8dd650d3417e51d8010e145abdf510bcf5ca183adad594e84b4582bd523e9289b87cdd23617dc05079b4c12f884d53f6f126542908aef44ec53d381e9983502eb32e32381ff59a9d9227c0d2b87517af5934852d68fd1d7c779f208b9885dbb1f226a3c5183bd0719116802ce8a58520355c402f9fe91a02993a00aa8275dd31397d04990df2a03254d2f1cf10371c22cb65db36593a11325ab1a873e72440883a9b928c789f8889603288c79f0ce73001ea50355f6f0906fb3060476447ea6b7b4d0217254735aa71266f2152377992f4a2124e4b034c2979f933dcf5cebc325fed3d044e3dd0b6f3fec12f987459fa65d78d504816d3064857b9fa54fec18b8512ed8b92174d8a909d878b409ad8e0e712d6549ac99a0c9d34da32589db0e1e740d57d9536af2695a61868a82bb95a918688882874218b306be023a170dfef382017221a19c8df5f6114450279287ff42ed270eb26518b20d4fe4fbd18ff3f37c256f9513e331824ce34e409c25398256d28042131541774fd07325cfb1b222bbf111992466606b3b008d75f221e2e9e0510dca93d6ce6ff37f3d601462bc1fec2d24e9435785250629bc60eebcea959fb00635075939dc89d5d294afe47e79f37f3e2c981bfa19f3b54e75cead662827dbd2f9344d37d6e2c4a9b5c4e3c466802552b7b6ebb665115085e5175882317c1a5045c4d3b646b4f186da7b018ef14f6dbf6d36a5151217ad4a900ec40e994bd44f3a9759d31dada118541365fd55370369ddeb9e959d90a093d8bf5c0b548023ba29103e58c4186145b36020fe916ba11adafd85e020fa9c0259308542a1b8bbb5650fd57b09e5ed05091b77d326c7325221e1f57625074988bc89fe620d33e424ab1712213a27e1c5b370354be4162bbc22ab6bb2d929ae0f940341c497b46dbf9ac3b08a9145ed5b96c46db331c3add2310fd59a5499c5827683bdb4249a7ba20f1c831025a05ef695c4f38666c737b3a1c0380d219605be3750ebe427ee0f62a9da0add398cf55c12293f07cf1ecd0111e8cdd281a89c3a49db544c97682f4a1f3c57052cf9f9ed0f33f61a7833ab86b0b66819236a4da57f3d7206d484f5272e037afa270b40ec05cc0e99b1704bc8914fda085ba53e5321142f1e089e5c3b4019a4317aba7be6cc45ebd065915bbd96879d53b1881d2abb4f5431050ea75c919b7b932e1650f2ae796f676baa72e2533e72446cb40e555183e070409d7e0356daaf500d73c0bd27fa232e4d8fb8a44f1f2ee2ae1d8233409353a35ed8d4f42f08841955ba6538b100d6b4a9bd2742a19605bf67b80193cac5adbe0daad118b315ee826089a108828e193aea45ebb379146e34981fda92717c1b0f9e0f474f8084fe4469092b87533fae8c6802f50ef703996f9689d63e358e5b8422e5e9f31a11bdbba9bb64f033d54218ab552ed455cfb137c50ea0979e89e776bdc261d63c7fc81aaaffb43f31ac7dbba20e452d8313d5204917575413e456560175d208e5d9a6bd88bfcd7391c7650a2f87252e5472869075b376cc26d6ed1dd7be4a037486a29a2a1d7525b1a7913a3b3fcd5145840b9f65bcc582cf034b90d99bfd6527b32eb695bfdd4e538e4ca195eff1328307bb9615cf4392e42fd20a496a3e9389cbc042f18dcb9f2bc963bdcf0ff5a43c93447f550644168134bfa3ec3eafaa7c4b08cc8b72be886b13a779caf6e05fe479fb92be8e493bbb0fca9ccacfda1b1cf4cd9074733db96bbbc08b81e8e5751d89f86617c161e4698dd9e413edfa8eb446bcf8a43677deb487dfd3d2c82e2591cec50eab8c4baecdbade9eb559af1f0143a87e11b56868910afaec31bfa41155bdd0047f12ef603d398f77b9bbeaf2e9dd3ba7a56b9d93fbfff15d5f081b8a55071ed8bd6f4368af26670e1d6e411fda9fb4cf0810f0ddd5cfe732617c115a9bc3fefd25be703278fe422bd1a57096c550114647882398ee75fdfcb9f53b6384c89991740fb017c37c4466f9d4bc91d1937db5d910b0f7ed73755e897cbe32f7fc758e1efdc97d51af4c1fb1c9ec36f319b4f10c27aa3c8f838be30f37ef44261533dedde757fbd419963a29b0beb60a1d5f20267cc5f26d9156b2350d4489a153a71161adf704119da417c5a6ba29819dceb30feec7026953e52a33bca10ef486b5074a23650513d2403a409adf2005136163e3401516d9dd32053a25011a182652467a253f1f5237a30d693b807ed699e6df27a2a76790836b8e5082f74ef4850b86e2ad397f6f9772a11723ec2eb5857f1274bd1ae10afe35fbd1123da6dc974bd1f8a3611b35c07702338d59829fe3eba3d71469ac25a34bbeb9a4c71689c8a3dcc0cfc8364b0c7d3457035956fae381bde5ec4d6442286504a9145fedd109f0874d9fb076a059d982345f534287c050a20c037dba733b16db7000b4e2399b3e7c13ffceae207cd1d01d5323bf64e6610e87b0a9ceb4721fa4aca4f1bb1559aeec34bef6d601b8e11631fce18cfd817498a932c012321712e7d5115476f4a505fd27171b72761fa086b7ab4b82ab2b5a1948d10408e73d0ed033fd40611f57ddc2ad37ac762203bd5862af357503678d988f59c858b06fd1cb4a37ddb1f871415cfbc281e90e77bfaa4349a60e0fa84d7b181f1f4836bcc5fffa487b87116b7fbf8d6fb0364e098793db89c178a1c1fb890d36c8c1b5e3e8f6678fe54595089932a23ab2c84c4b8d9e9dfbbd70cb8ff1cf4dcfb05c6d6e68485b184587592792ea6cfa99e9ac4cee02f37a1a08ecedf7630f049c12f2fbc5a63d33187bef0bf50c1f079682f0ff5986091ce41891b3783cd5174a9e363475863b90087ee092bd1843edd5fb6a46b98a55d5da32ae8ecbcbc5171ce8ae7dd5f15bde2f673f79ac08b089f48d2383be7b7f15e37ca7bc4e2e1a15c172b165c7817f0d792b1b98a54b06c63a73a1a26180185fc5ea40e8755f69b7a8776c8a5de79a99f8e707f3e198a6cb08325b145e0d0a95860c4d26084b5eb39509e9500547a1c62228529fdd6659e6847e98ee57bec7a7cd307599e242092f1916750f3192d595e49c2519f92d293af9757f077bd84791fdb765216008806d092f2dfa49ae5e78a52a6c462fa123721da9be666db9319c60d82079e908bb856f6cbf476798a7c8fa02b216f5fe79937ecd811ce9722f81f5854d59e8d7e5afe70308bde1006e818403b074e0d526d12c11740893374a97997529d54e3eb44fe7a09207fd1ab903a73f4f496f71b33e52672d99e4a620347bb79b2666954b9140189add08a756c70bb92c5e4d15be93adde5e79155e3739cb93a5857deab17f60babf146f058e476c16c08cf4ce3649f4963021a25709b0a742619025bbe17662466ccfa31d8d72e882e1316eab62b8084c882671901e033e3db07fd8fd84238b92be9e05a8a389e7e8ade9ea7a5c15071117bb550d9de727862e94b97b6aed1fe669937ddc9e2a893b620eb438bf0ab592dbe05e4d10679389299b3d3188c82866c3ef0633d38b9c6b9f17194baf21701a0c390bda239e4522645a294b507d5b6c0213cdbaca3e27e6ddc207a36723af1a95ca03bef3e61d98b8dd0d092c57e3731389e3b024f9f708c47b29fb3a1a7e003b1ae08469077aea25089915e6200a50af1718d8517c052e8547280ea123eafa051899817f7b9e2c5f44dba7abca4fa9dd8f6c9ef5866843f9ad3303e907e8d53ec9040f79a768de0e9db124d8237dd1b017b60200026dbb5cf9fbec0ae1481d801b4b8e210b55a2e95fd1c405bbac1e9cf422421d6328042907d848df1406be81088996daea7ddcd363f523f934eb8be1fffd674b5fb0ce6bb97048d28b187b2f9cc18015a4ab0d0a0fda826a9a1bb728315fc729447b5fbc23a53b0e6fe5a23280c708a8a2c748fc2b553b85d4f1a7a6e22db6d51759b8a20ae1efb23b12470e7b0ce2c307240a11af0e9100004b1892b79e761fa54184ed0271a7ece6e14e914f71daf003b6ba8666f19e9d13f7ba8504d9d1f16d9dab32ffa75445bb187c4e77719e9d9d1b7b2bed8c7f02badcfe3fa5ae90d927cdb994820e0e2e1eeb86970b69cd19cbfa54ea3fb2863984e7e1757d5d81b54fb179d927440f39077a497c23f6bb26a87d87bc5cfd952d105fdcc673647d021e8c5114b024bae0a8980ec17755040bb2b90c771e0dba1c7cad6e4bf12fcc85c1ee0084ee4fc32a8f75277916e5052c0b114a908a24ad0fe7856e0b202f298f0fbd53a41d2ff532bb63ea0cdefd9eb38d35aa0f032d302bcc9c7c6adbc16b1189b71933870be76f08edc63b4253bebe5dc144dbae6d0cc508611a39bc314efde44e2461c40d4eb5c11d2a7d424dd2cb8f1f572ef1055964373391a4efc00a775d1081c8c20075580785fd4024eb9908272dd211970021c1de8f92c7a249a34cfecfa266327a82678c31023d3f9f62cbc5331d5fe77f03c94b17fe058ebd73e49b185f3991444a9faa2a0d89521528ae29732f8a16f50604b8ddb2e51ad733a50b19160caf5ddb55dda869e2a87d5e6d9bb64934e79d0d1e93670f6f0cf3dd29af2da2e1cc950c7e257794a5096ec8fcea08e72d56cd1b34eed3e8a22726757b1264929f8c4a23236a27b60cdc98cd14a3ec82a953bb022900a55bde7e587fe5aec10daf2b8f4b24b8053deb136e8c349fd9f12dca52ee0a614dac05ae2f5642175b8ae1bcf06a49b88521fa29f6ddf9fcbb08938ec6be91df0969de791fb8b095cebef2d0c963c217638a94adf6e9af4df530581331459da0249ef5f9499a3c34f602b7ba40961e93e6d7b766e4310c29d64ea1a446688d5fdfe5089205144e0f1a158bffe7b202e14e6e4b61465eddbbefec5c68295bb0ccf1b272ba411e8e9374ce191383089086a74386ab411ea1b89902be7b56dbf0004a1279384b3ebd2467a941bf7742b1bbc097793b7a7942476484c145c1161d64698261a2fa120927264a159b3612490c103e3e1c919afdad7fc9a364d1ce9c3371963cf46982008625cfc497242a8f1a600765aa6786e0962445fc17a5c61d279e6a3927a5452173eafa551b890acd0aaf2e5cd1eda19a5d4f7191f1fdab650b736b5f36099bc703fdad359fc36b44803b6479f7a8be4cb76b1f0d23f6febf2cc48a6d5f244e9e0c411d8de830149e043d99d48ed2ebd544d831d3632dd3ae7bbe8d75d4d931d20fc545051fb5c4b203242136d7e46c3f89da889fe3f7823dca91c59d30886e1d0ba3a117c2e012393aef7124a56d25dd5db06eb79111108bcc65338f037e9155bfcf247f99e508ae8bda6b8b7d7c0969cd0fa8aeacaf5cb8c75d0e080df70afb467f0f554e1722855abd1f4bb7562901667d3b4f256cb29952552a55d5640915ab2b974180eea5a3d46623a902b6ceb4556908f49fb055471b86bfe5c73a041067edbb0e7b5825e4975a1be425cd399080a87c858d6bc7cb19e5f938f88d2d7f39f008b301d605abbc5f7d9201e6007f38798bacb58bc98b98eb9e3e2bc51a85d2f4d2195725943deafb38b56f3578a6cf17bae7f64411191504a2ae2c4faa0159f0ee01e6f10feab0259bddca452369350dfe02e4243e17ed0e62b9f26193193b7fe203dc5126aafd6c0eff2d674e6aa56d0f3eb76d0c38836099db9b88225d852d6905853012b1cb27da40ed0f420868f53e3d9e8cae9c289c0a408209d32ef85c3c919b236a15ea2f8bba4b2b9444affd3ad5da868631177506b5a765063127250682c70b79a2a702063057a507f6c7b7906d2460469e8425a9a762449920f9645a2196f387beb56a00610860465e842569a62444582196258620c125a924c7f79564478027268a2b96ff17ab969f07cb9105fca1016f0750971195050601726517aac3f48d2f16eb97a416e6276e864b0cef061686c0f42459ae472e272e878b06ec87c906a6871306448777c6f185a244be81277922c500b633876719207964db203b649321876184a195a086fe87db06bc8719067687230612874988a3b4e5e416c6aa0060386647842e65176186ea074f8628070d866988a0e4e4636179ea056160a2270e866b06cd87a206978a6b86af0241466f17db968f27f7501f17eb965f070b95020545b623a12638ae8426138195c5075e863b071d86720fa7fb6920a040e397e649f4c8b04204c507e57006f1d426056349a11da697020222870520a2ab0742cf15eb9445e36b96ff07ab930f5a62043139631ba4157517c1863a071f867806dd87b206e787d24255cb6b87d2069b475f8862474e81245922c6260630af90094dc5e5fa2487934aaf179a86d2a7d786c389f5e9a16445a5a266d5a62039243926c64a0060986647268a44426b9d9ab121cd40ce5bc89568b0a9f418a089e8221d49f122a08e620727c96b972686602049fbea363206457620a12798a7992b970f27d61701e9e5f9a59e45e1215165c32f07e315ef1642a702a78b0ba3b14cff013865982e9ba3446f77f0f0b042a21163d26b946f155b840990a2777f8c6b2520d7e60060895a056173dc2f67426948b119e588a4a11f80438509f6d18087798ff861479f128605a4d9f348bb59f108bac86ed7cf13aa0a606866f7df11e792ad286e242e8f6058ba0863340e8e2058b7446f241f1daa0ca3b861a46f1b2a0323c9fb88bc89fa092325cb98a31469a92a158a0624e9f90527544b942e8026292ba43b95ae8de6592e140b93a28766788f1377912f13eb999f10aa0662086ca5af1e6b9c2e8fd6c8bbc5fc4ae48306dbef1b6a02e2586e05cf1a2a1da269e6f88e85779b9b4865035f192a01b589f584b98864520e86e078b042707244857fc4b785f9dc4f13a79b6e9d91743b486e825e864188b6486482af1f0b9eaf1fab9b0f1eeb9bae8be198bbc86802be8611a8ba45f704b91dab9a6f1e6a013539f8c4b605ffccef186b9d6480f1c06f28e71925a3ba06a409f184bf3dab942f182a088569f6492e838a03e579f14927c39a01a489f08929826a046499f3c4b34475e307c577922d25f818b849f8892c025b9d2e89603923722b9a6314e9a4b939f848be8864537f196797ed25f678af071af8bae779c72b7064f9d13e6fafab2d6facab2c6fadab2b6faaab2a6fabab296fa8ab286fa9ab276af8bc377b7b8'
def unhex(hex_string):
import binascii
if type(hex_string) == str:
return binascii.unhexlify(hex_string.encode('utf-8'))
else:
return binascii.unhexlify(hex_string)
data = unhex(data_string)
import struct
def decrypt_dw(data, dw_key, byte_key):
out = b''
for i in range(0,(len(data)//4)*4,4):
tmp = struct.unpack('<I', data[i:i+4])[0]
out += struct.pack('<I', tmp ^ dw_key)
# Decrypt tail
tail_bytes = len(data) % 4
if tail_bytes > 0:
tmp_out = []
for c in data[-tail_bytes:]:
tmp_out.append(c ^ byte_key)
out += bytes(tmp_out)
return out
out = decrypt_dw(data, 0x76186250, 0x50)
payload_size = struct.unpack('<I',out[:4])[0]
payload = out[4:]
open('/tmp/out1.bin','wb').write(payload)
Decompression
Once the stage 3 data is decrypted it is also decompressed with the LZSA2 algorithm. We matched this with a blog. The LZSA algorithm is detailed on this github Emmanuel Marty/LZSA.
Stage 3
Destroyed PE Format
The decrypted stage 3 is actually a PE file but the header has been destroyed. The sections remain intact, and can be see starting at offset 0x400. There are some notes on reconstructing the PE file on the Unpacking Smokeloader and Reconstructing PE Programatically using LIEF blog.
Config
def rc4crypt(data, key):
#If the input is a string convert to byte arrays
if type(data) == str:
data = data.encode('utf-8')
if type(key) == str:
key = key.encode('utf-8')
x = 0
box = list(range(256))
for i in range(256):
x = (x + box[i] + key[i % len(key)]) % 256
box[i], box[x] = box[x], box[i]
x = 0
y = 0
out = []
for c in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(c ^ box[(box[x] + box[y]) % 256])
return bytes(out)
key = 0x0E63C2D43
str_data = unhex('2d8bf98b00db96cfde364292ce91c9058bad2360a60d67e613d64f4fc44ce8809ee356a4ca957ea0a796a902593924b0e29904dfcd92940e61888384c91983a732139d0660ec0dce4f048a68fd95cfe14da2ca0c82e98911d8c5d3c37c488d8c09afe29c11dcc58f9f680b93e18a17c1c2bf823b56840dbfe88700c4c3929420028498930696fe9a029b9e0882e98911d8c5d3c30696ff931dc7c2058ce19a439a0794e49118dcd8900694fecd2f9b9e0687e38c11d8c50790e59a1cc49fd20a90fb9c26cdde93983d4207b5e88d03c1c38e04cdef960404c6feb93604c6bdcd080ac6feda4090f4c5c16a740cc68d8c70f4acc5f13a2c92e008c68d8c708dac93f11c918d9a70cfac93f1242c93e0c5a658ece14660d41b14a97f852a03aa12c68dbe70f8acb0f1162ca0e0a2a62bece4460cc68dab70edacadf1022cc4e008cd8d9a70d0ac85f108cd8d9b70c4ac8cf108cd8d9d70c9ac94f120d98da570c7ac8ef1372ccfe0bfa60eeca44621d41c14e07fc62a19aa488597a308b38db070fbacb4f15ea08d9070c6ac94f1372c8fe082a647ec954636d41814ec7f9a2a50aa4c8595a3fe3fabb8930dacc1838715363d9b3c77c08abf83fcc01d61c0e92bca8ffc69abfbde3d66d38f71578e6b29684526e658de2ab7f813916f65a6cb95b942b0088c8d8f70cdac8ef110ab8d9070dbac94f1682cc1e0d3a619ec0ab38dab7099acd0f11f2c26d28dc67091acd9f17f2cd0e0c7a647ecf2467fd43c14b97f902a4aaa1d85d5a3b43ff7b8ca0d42a58d9670daac85f1342c8ee08ea64aec85462ad40e14e87fd52a1caa5985c5a3cc3fb5b8950db8c191870436269b7377ef8af783e1c05e61c3e97ccaddfc2cabeede44a28d9c70cbac85f1222c95e0cca64aeceb4660d44214847faa2a22aa488583a3eb3fb5b89f0dbdc1d88741363c9b2777da8ae083bec01f6198e979caabfc61abeede7d6646a28d9c70cbac85f1222c95e0cca64aeceb4660d44214847faa2a22aa488583a3eb3fb5b89f0dbdc1d88741363c9b2777da8ae083f7c00a6198e973caddfc17abb8de21668e8f08cd8d9c70c7ac8df108cd8d9070daac87f108cd8d9170cdac94f100000074311e0d90602cc7978436088dcbe6c297873c97b2a604b194b5047e796040f4064a1927c4f15868b45c2ed186330ddb60a93cf3b4691a1e9a2306227810f2dccdd510b06c90349f000000006c1100108c110010b412001020130010941300104c110010a4100010e8100010b813001074130010c4170010a417001080100010c810001017008bbd0d161ec11409c1cca01d2778f6253717e296e6324b153620a909a60d1823f27ce0fc29685fa33464f5bf3d7697c30dbbf100a5541ed1b8ddca8a7067e0')
ptr = 0
while ptr <= 0x319:
str_len = str_data[ptr]
print(rc4crypt(str_data[ptr+1:ptr+1+str_len], struct.pack('<I', key)).replace(b'\x00',b''))
ptr = ptr+1+str_len
ll = 0x18
key = 0x0C0C8260
data = unhex('54cbbe8ff42e4337a7145098628286e408bdcfdd95c30f25')
print(rc4crypt(data, struct.pack('<I', key)))
key = 0x0AC89E485
data = unhex('4c438a3e56df89d4297f8dfa9e83cb81a4904c63a41e1f6692ac00')
print(rc4crypt(data, struct.pack('<I', key)))
key = 0x917A57DC
data = unhex('6ecb20fa24d58995911a5d59dec7e4dd74f11ee2c7fc46d56191')
print(rc4crypt(data, struct.pack('<I', key)))
key = 0x3B7045D5
data = unhex('6afbb21cf76f16be6d09abf21a6aa407d83cbcad630f5597a205ae4fc76b3bba')
print(rc4crypt(data, struct.pack('<I', key)))
key = 0x884CA0A1
data = unhex('bbcb0f8124742be0ae4f8aaf0941a7d496094d98358ac42666')
print(rc4crypt(data, struct.pack('<I', key)))
s3 = open('/tmp/out1_sect1_400.bin', 'rb').read()
table_start = 0x76c
table_end = 0x7A0
for ptr in range(table_start, table_end, 4):
c2_data_address = struct.unpack('<I', s3[ptr:ptr+4])[0]
c2_data_offset = c2_data_address - 0x10001000
c2_data_len = s3[c2_data_offset]
c2_data_key = s3[c2_data_offset+1:c2_data_offset+1+4]
c2_data = s3[c2_data_offset+1+4:c2_data_offset+1+4+c2_data_len]
print(rc4crypt(c2_data, c2_data_key))