mirror of
https://github.com/aljazceru/securedorg.github.io.git
synced 2025-12-18 22:54:19 +01:00
adding final sections
This commit is contained in:
44
RE102/decrypt_shellcode.py
Normal file
44
RE102/decrypt_shellcode.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def key_schedule(key):
|
||||
keylength = len(key)
|
||||
S = range(256)
|
||||
j = 0
|
||||
for i in range(256):
|
||||
k = ord(key[i % keylength])
|
||||
j = (j + S[i] + k) % 256
|
||||
S[i], S[j] = S[j], S[i] # swap
|
||||
return S, j
|
||||
|
||||
|
||||
with open(sys.argv[1], 'rb') as key_file, open(sys.argv[2], 'rb') as encrypted, open("decrypted_shellcode.bin", 'wb') as out:
|
||||
key_size = os.path.getsize(sys.argv[1]) # 0x20
|
||||
key = key_file.read(key_size)
|
||||
S, j = key_schedule(key)
|
||||
|
||||
"""
|
||||
A normal RC4 stream algorithm
|
||||
resets j before a second use.
|
||||
"""
|
||||
# j = 0
|
||||
|
||||
i = 0
|
||||
|
||||
shellcode_size = os.path.getsize(sys.argv[2]) # 0x65E4
|
||||
|
||||
while (shellcode_size > 0):
|
||||
char = encrypted.read(1)
|
||||
i = (i + 1) % 256
|
||||
j = (j + S[i]) % 256
|
||||
|
||||
# swap
|
||||
S[i], S[j] = S[j], S[i]
|
||||
k = S[(S[i] + S[j]) % 256]
|
||||
shellcode_size -= 1
|
||||
|
||||
out.write(chr(ord(char) ^ k))
|
||||
out.close()
|
||||
key_file.close()
|
||||
encrypted.close()
|
||||
BIN
RE102/images/Section8_Conclusion.png
Normal file
BIN
RE102/images/Section8_Conclusion.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
@@ -16,13 +16,25 @@ The environment setup is the same. Please refer to this page [Section 1: Fundame
|
||||
|
||||
## Download the Unknown Malware
|
||||
|
||||
[**HERE**](#)
|
||||
[**HERE**](https://drive.google.com/file/d/0B_0DJl2kuzoNYU9jYldCdmw0d2s/view?usp=sharing)
|
||||
|
||||
Password is "infected"
|
||||
|
||||
Sha1 for zip file
|
||||
```
|
||||
f77f58812d5883775e59dfe952239d7dddfbd332
|
||||
```
|
||||
|
||||
Sha256 Malware inside
|
||||
```
|
||||
8be8abab0f3ebcc18e7b8b3c437feb073fa7b9b30e8b1eef81451f0938b2a52a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# WARNING - DO NOT UNZIP OR RUN THIS OUTSIDE OF THE VM #
|
||||
|
||||
1. Run the Victim VM and copy over the malware.zip into the VM.
|
||||
2. Unzip ** Warning - DO NOT UNZIP THIS OUTSIDE OF THE VM **
|
||||
2. Unzip **Warning - DO NOT UNZIP THIS OUTSIDE OF THE VM**
|
||||
|
||||
[Intro <- Back](https://securedorg.github.io/RE102/intro) | [Next -> Information Gathering](https://securedorg.github.io/RE102/section2)
|
||||
|
||||
136
RE102/re102_section6.1.md
Normal file
136
RE102/re102_section6.1.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
layout: default
|
||||
permalink: /RE102/section6.1/
|
||||
title: Setup
|
||||
---
|
||||
[Go Back to Reverse Engineering Malware 102](https://securedorg.github.io/RE102/)
|
||||
|
||||
# Section 6.1: The Unpacking Script #
|
||||
|
||||
Here is the full unpacking script. Extract the raw resource 1000 as a binary file as the first argument. It will output the exe as decrypted_payload.exe
|
||||
|
||||
```
|
||||
import os
|
||||
import sys
|
||||
|
||||
# key sizes
|
||||
key1size = 32 # 0x20
|
||||
key2size = 64 # 0x40
|
||||
|
||||
# offset to key2
|
||||
key2_offset = 720 # 2D0
|
||||
|
||||
# offset to payload
|
||||
payload_offset = 792 # 0x318
|
||||
|
||||
# offset to first instruction
|
||||
junk_char_length_offset = 100 # 0x64
|
||||
good_char_length_offset = 168 # 0xA8
|
||||
|
||||
# header bytes
|
||||
header = 'MZ'
|
||||
|
||||
|
||||
def key_schedule(_key):
|
||||
key = _key
|
||||
if not isinstance(_key, list):
|
||||
key = list(_key)
|
||||
keylength = len(key)
|
||||
S = range(256)
|
||||
j = 0
|
||||
for i in range(256):
|
||||
k = key[i % keylength]
|
||||
if not isinstance(key[i % keylength], int):
|
||||
k = ord(key[i % keylength])
|
||||
j = (j + S[i] + k) % 256
|
||||
S[i], S[j] = S[j], S[i] # swap
|
||||
return S, j
|
||||
|
||||
|
||||
def RC4_decrypt(_key, _enc):
|
||||
result = []
|
||||
S, j = key_schedule(_key)
|
||||
enc = _enc
|
||||
if not isinstance(_enc, list):
|
||||
enc = list(_enc)
|
||||
m = len(enc)
|
||||
i = 0
|
||||
for c in enc:
|
||||
i = (i + 1) % 256
|
||||
j = (j + S[i]) % 256
|
||||
S[i], S[j] = S[j], S[i]
|
||||
k = S[(S[i] + S[j]) % 256]
|
||||
m -= 1
|
||||
if not isinstance(c, int):
|
||||
result.append(ord(c) ^ k)
|
||||
else:
|
||||
result.append(c ^ k)
|
||||
return result
|
||||
|
||||
|
||||
def deflate_payload(junk, good_data, _data):
|
||||
data = list(_data)
|
||||
new_data = []
|
||||
j = 0
|
||||
k = 0
|
||||
new_data.append(ord(data[0]))
|
||||
i = 1
|
||||
while i < len(data):
|
||||
if j != junk:
|
||||
j = junk
|
||||
i += j
|
||||
if j == junk:
|
||||
if k < good_data:
|
||||
new_data.append(ord(data[i]))
|
||||
k += 1
|
||||
i += 1
|
||||
else:
|
||||
j = 0
|
||||
k = 0
|
||||
return new_data
|
||||
|
||||
|
||||
with open(sys.argv[1], 'rb') as encrypted_file:
|
||||
|
||||
# Get the file size
|
||||
file_size = os.path.getsize(sys.argv[1])
|
||||
|
||||
# Get the first key of 0x20 bytes
|
||||
key1 = encrypted_file.read(key1size)
|
||||
|
||||
# Get the start of deflate instructions
|
||||
encrypted_info = encrypted_file.read(payload_offset - key1size)
|
||||
|
||||
# Get the bytes for the payload
|
||||
encrypted_payload = encrypted_file.read(file_size-payload_offset)
|
||||
|
||||
# 1. Decrypt the deflation instructions
|
||||
decrypted_info = RC4_decrypt(key1, encrypted_info)
|
||||
|
||||
# 2. Get instructions from the decrypted data
|
||||
junk_char_length = decrypted_info[junk_char_length_offset-key1size]
|
||||
good_char_length = decrypted_info[good_char_length_offset-key1size]
|
||||
|
||||
# 3. deflate payload
|
||||
deflated_payload = deflate_payload(junk_char_length, good_char_length, encrypted_payload)
|
||||
|
||||
# 4. get key2
|
||||
key2 = []
|
||||
for i in range(key2size):
|
||||
key2.append(decrypted_info[(key2_offset-key1size)+i])
|
||||
|
||||
# 5. decrypt enc3
|
||||
decrypted_payload = RC4_decrypt(key2, deflated_payload)
|
||||
|
||||
# 6. fix header
|
||||
for i in range(len(header)):
|
||||
decrypted_payload[i] = ord(header[i])
|
||||
|
||||
# write to file
|
||||
with open("decrypted_payload.exe", 'wb') as out:
|
||||
for i in decrypted_payload:
|
||||
out.write(chr(i))
|
||||
out.close()
|
||||
```
|
||||
|
||||
[Section 6 <- Back](https://securedorg.github.io/RE102/section6) | [Next -> Extra Fun](https://securedorg.github.io/RE102/section7)
|
||||
22
RE102/re102_section7.md
Normal file
22
RE102/re102_section7.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: default
|
||||
permalink: /RE102/section7/
|
||||
title: Setup
|
||||
---
|
||||
[Go Back to Reverse Engineering Malware 102](https://securedorg.github.io/RE102/)
|
||||
|
||||
# Section 7: Extra Fun #
|
||||
|
||||
This concludes the workshop but you can apply the same unpacker to the resources in this malware. The payload exe is:
|
||||
1. UPX packed
|
||||
2. Has 3 resources using the same packer
|
||||
|
||||
As an exercise I recommend going through them on your own.
|
||||
|
||||
Most packers are bought and sold on underground forums or traded amongst malware authors. The flowing sample called [Rombertik](https://en.wikipedia.org/wiki/Rombertik) uses this same packer. For fun you can check it out:
|
||||
|
||||
```
|
||||
77bacb44132eba894ff4cb9c8aa50c3e9c6a26a08f93168f65c48571fdf48e2a
|
||||
```
|
||||
|
||||
[Section 6.1 <- Back](https://securedorg.github.io/RE102/section6.1) | [Next -> Conclusion](https://securedorg.github.io/RE102/section8)
|
||||
22
RE102/re102_section8.md
Normal file
22
RE102/re102_section8.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: default
|
||||
permalink: /RE102/section7/
|
||||
title: Setup
|
||||
---
|
||||
[Go Back to Reverse Engineering Malware 102](https://securedorg.github.io/RE102/)
|
||||
|
||||
# Section 8: Conclusion #
|
||||
|
||||
This concludes workshop RE102. I hope you enjoyed the levels of obfuscation and evasion. Here is a summary of what the malware’s packer does.
|
||||
|
||||
```
|
||||
8be8abab0f3ebcc18e7b8b3c437feb073fa7b9b30e8b1eef81451f0938b2a52a
|
||||
```
|
||||
|
||||
The purpose of this workshop was to get you familiar with Anti Reverse Engineering, Encryption, VM Evasion and Packing techniques. As you saw this malware's packer had multiple layers of shellcode and tricks to throw off a reverse engineer. But by breaking things down step by step, you were able to work your way through each challenge.
|
||||
|
||||

|
||||
|
||||
Special thanks to Ashkan.
|
||||
|
||||
[Section 7 <- Back](https://securedorg.github.io/RE102/section7)
|
||||
121
RE102/re102_unpacker.py
Normal file
121
RE102/re102_unpacker.py
Normal file
@@ -0,0 +1,121 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# key sizes
|
||||
key1size = 32 # 0x20
|
||||
key2size = 64 # 0x40
|
||||
|
||||
# offset to key2
|
||||
key2_offset = 720 # 2D0
|
||||
|
||||
# offset to payload
|
||||
payload_offset = 792 # 0x318
|
||||
|
||||
# offset to first instruction
|
||||
junk_char_length_offset = 100 # 0x64
|
||||
good_char_length_offset = 168 # 0xA8
|
||||
|
||||
# header bytes
|
||||
header = 'MZ'
|
||||
|
||||
|
||||
def key_schedule(_key):
|
||||
key = _key
|
||||
if not isinstance(_key, list):
|
||||
key = list(_key)
|
||||
keylength = len(key)
|
||||
S = range(256)
|
||||
j = 0
|
||||
for i in range(256):
|
||||
k = key[i % keylength]
|
||||
if not isinstance(key[i % keylength], int):
|
||||
k = ord(key[i % keylength])
|
||||
j = (j + S[i] + k) % 256
|
||||
S[i], S[j] = S[j], S[i] # swap
|
||||
return S, j
|
||||
|
||||
|
||||
def RC4_decrypt(_key, _enc):
|
||||
result = []
|
||||
S, j = key_schedule(_key)
|
||||
enc = _enc
|
||||
if not isinstance(_enc, list):
|
||||
enc = list(_enc)
|
||||
m = len(enc)
|
||||
i = 0
|
||||
for c in enc:
|
||||
i = (i + 1) % 256
|
||||
j = (j + S[i]) % 256
|
||||
S[i], S[j] = S[j], S[i]
|
||||
k = S[(S[i] + S[j]) % 256]
|
||||
m -= 1
|
||||
if not isinstance(c, int):
|
||||
result.append(ord(c) ^ k)
|
||||
else:
|
||||
result.append(c ^ k)
|
||||
return result
|
||||
|
||||
|
||||
def deflate_payload(junk, good_data, _data):
|
||||
data = list(_data)
|
||||
new_data = []
|
||||
j = 0
|
||||
k = 0
|
||||
new_data.append(ord(data[0]))
|
||||
i = 1
|
||||
while i < len(data):
|
||||
if j != junk:
|
||||
j = junk
|
||||
i += j
|
||||
if j == junk:
|
||||
if k < good_data:
|
||||
new_data.append(ord(data[i]))
|
||||
k += 1
|
||||
i += 1
|
||||
else:
|
||||
j = 0
|
||||
k = 0
|
||||
return new_data
|
||||
|
||||
|
||||
with open(sys.argv[1], 'rb') as encrypted_file:
|
||||
|
||||
# Get the file size
|
||||
file_size = os.path.getsize(sys.argv[1])
|
||||
|
||||
# Get the first key of 0x20 bytes
|
||||
key1 = encrypted_file.read(key1size)
|
||||
|
||||
# Get the start of deflate instructions
|
||||
encrypted_info = encrypted_file.read(payload_offset - key1size)
|
||||
|
||||
# Get the bytes for the payload
|
||||
encrypted_payload = encrypted_file.read(file_size-payload_offset)
|
||||
|
||||
# 1. Decrypt the deflation instructions
|
||||
decrypted_info = RC4_decrypt(key1, encrypted_info)
|
||||
|
||||
# 2. Get instructions from the decrypted data
|
||||
junk_char_length = decrypted_info[junk_char_length_offset-key1size]
|
||||
good_char_length = decrypted_info[good_char_length_offset-key1size]
|
||||
|
||||
# 3. deflate payload
|
||||
deflated_payload = deflate_payload(junk_char_length, good_char_length, encrypted_payload)
|
||||
|
||||
# 4. get key2
|
||||
key2 = []
|
||||
for i in range(key2size):
|
||||
key2.append(decrypted_info[(key2_offset-key1size)+i])
|
||||
|
||||
# 5. decrypt enc3
|
||||
decrypted_payload = RC4_decrypt(key2, deflated_payload)
|
||||
|
||||
# 6. fix header
|
||||
for i in range(len(header)):
|
||||
decrypted_payload[i] = ord(header[i])
|
||||
|
||||
# write to file
|
||||
with open("decrypted_payload.exe", 'wb') as out:
|
||||
for i in decrypted_payload:
|
||||
out.write(chr(i))
|
||||
out.close()
|
||||
Reference in New Issue
Block a user