Skip to content

Commit e9db944

Browse files
authored
Merge pull request #775 from zeroSteiner/fix/met/py-embed-crypto
Move the crypto code into the Python Meterpreter
2 parents fee606a + cc628e0 commit e9db944

2 files changed

Lines changed: 284 additions & 10 deletions

File tree

python/meterpreter/meterpreter.py

Lines changed: 283 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/python
22
import binascii
33
import code
4+
import copy
45
import os
56
import platform
67
import random
@@ -49,6 +50,7 @@
4950
NULL_BYTE = bytes('\x00', 'UTF-8')
5051
long = int
5152
unicode = lambda x: (x.decode('UTF-8') if isinstance(x, bytes) else x)
53+
xrange = range
5254

5355
# reseed the random generator.
5456
random.seed()
@@ -948,7 +950,7 @@ def decrypt_packet(self, pkt):
948950
if enc_flag == ENC_AES256:
949951
iv = raw[PACKET_HEADER_SIZE:PACKET_HEADER_SIZE+16]
950952
encrypted = raw[PACKET_HEADER_SIZE+len(iv):]
951-
return met_aes_decrypt(self.aes_key, iv, encrypted)
953+
return AES_CBC(self.aes_key).decrypt(iv, encrypted)
952954
else:
953955
return raw[PACKET_HEADER_SIZE:]
954956
return None
@@ -977,7 +979,7 @@ def encrypt_packet(self, pkt):
977979
# sending it back to MSF, and it won't be able to decrypt it yet.
978980
if self.aes_enabled:
979981
iv = rand_bytes(16)
980-
enc = iv + met_aes_encrypt(self.aes_key, iv, pkt[8:])
982+
enc = iv + AES_CBC(self.aes_key).encrypt(iv, pkt[8:])
981983
hdr = struct.pack('>I', len(enc) + 8) + pkt[4:8]
982984
pkt = hdr + enc
983985
# We change the packet encryption type to tell MSF that
@@ -1510,17 +1512,17 @@ def _core_patch_url(self, request, response):
15101512
return ERROR_SUCCESS, response
15111513

15121514
def _core_negotiate_tlv_encryption(self, request, response):
1513-
debug_print('[*] Negotiating TLV encryption')
1515+
debug_print('[*] negotiating TLV encryption')
15141516
self.transport.aes_key = rand_bytes(32)
15151517
self.transport.aes_enabled = False
15161518
response += tlv_pack(TLV_TYPE_SYM_KEY_TYPE, ENC_AES256)
15171519
der = packet_get_tlv(request, TLV_TYPE_RSA_PUB_KEY)['value'].strip()
1518-
debug_print('[*] RSA key: ' + str(binascii.b2a_hex(der)))
1519-
debug_print('[*] AES key: ' + hex(met_rsa.b2i(self.transport.aes_key)))
1520-
enc_key = met_rsa_encrypt(der, self.transport.aes_key)
1521-
debug_print('[*] Encrypted AES key: ' + hex(met_rsa.b2i(enc_key)))
1520+
debug_print('[*] received RSA key: ' + str(binascii.b2a_hex(der)))
1521+
debug_print('[*] generated AES key: ' + str(binascii.b2a_hex(self.transport.aes_key)))
1522+
enc_key = RSA(der).encrypt(self.transport.aes_key)
1523+
debug_print('[*] sending encrypted AES key: ' + hex(RSA.b2i(enc_key)))
15221524
response += tlv_pack(TLV_TYPE_ENC_SYM_KEY, enc_key)
1523-
debug_print('[*] TLV encryption sorted')
1525+
debug_print('[*] finished negotiating TLV encryption')
15241526
return ERROR_SUCCESS, response
15251527

15261528
def _core_loadlib(self, request, response):
@@ -1740,7 +1742,279 @@ def create_response(self, request):
17401742
debug_print("[*] sending response packet")
17411743
return response + tlv_pack(TLV_TYPE_RESULT, result)
17421744

1743-
# PATCH-SETUP-ENCRYPTION #
1745+
class AES_CBC(object):
1746+
nrs = {16: 10, 24: 12, 32: 14}
1747+
S = [
1748+
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
1749+
118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156,
1750+
164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241,
1751+
113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
1752+
235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179,
1753+
41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57,
1754+
74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127,
1755+
80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218,
1756+
33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167,
1757+
126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238,
1758+
184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211,
1759+
172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108,
1760+
86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198,
1761+
232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246,
1762+
14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217,
1763+
142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191,
1764+
230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
1765+
]
1766+
1767+
@staticmethod
1768+
def _gmul_helper(a, b):
1769+
r = 0
1770+
while b:
1771+
if b & 1:
1772+
r ^= a
1773+
a <<= 1
1774+
if a > 255:
1775+
a ^= 0x11B
1776+
b >>= 1
1777+
return r
1778+
1779+
@staticmethod
1780+
def _rcon_helper(gmul_func):
1781+
return [gmul_func(1, 1 << n) for n in range(30)]
1782+
1783+
@staticmethod
1784+
def _ror32(x):
1785+
return ((x >> 8) | (x << 24)) & 0xFFFFFFFF
1786+
1787+
@staticmethod
1788+
def _Si_helper(S):
1789+
return [S.index(n) for n in range(len(S))]
1790+
1791+
@staticmethod
1792+
def _mix_helper(n, vec, gmul_func):
1793+
return sum(gmul_func(n, v) << (24 - 8 * shift) for shift, v in enumerate(vec))
1794+
1795+
@staticmethod
1796+
def _mixl_helper(S, vec, gmul_func, mix_func):
1797+
return [mix_func(s, vec, gmul_func) for s in S]
1798+
1799+
@staticmethod
1800+
def _rorl_helper(T, ror_func):
1801+
return [ror_func(t) for t in T]
1802+
1803+
Si = _Si_helper.__get__(object)(S)
1804+
rcon = _rcon_helper.__get__(object)(_gmul_helper.__get__(object))
1805+
T1 = _mixl_helper.__get__(object)(S, (2, 1, 1, 3), _gmul_helper.__get__(object), _mix_helper.__get__(object))
1806+
T2 = _rorl_helper.__get__(object)(T1, _ror32.__get__(object))
1807+
T3 = _rorl_helper.__get__(object)(T2, _ror32.__get__(object))
1808+
T4 = _rorl_helper.__get__(object)(T3, _ror32.__get__(object))
1809+
T5 = _mixl_helper.__get__(object)(Si, (14, 9, 13, 11), _gmul_helper.__get__(object), _mix_helper.__get__(object))
1810+
T6 = _rorl_helper.__get__(object)(T5, _ror32.__get__(object))
1811+
T7 = _rorl_helper.__get__(object)(T6, _ror32.__get__(object))
1812+
T8 = _rorl_helper.__get__(object)(T7, _ror32.__get__(object))
1813+
U1 = _mixl_helper.__get__(object)(list(range(256)), (14, 9, 13, 11), _gmul_helper.__get__(object), _mix_helper.__get__(object))
1814+
U2 = _rorl_helper.__get__(object)(U1, _ror32.__get__(object))
1815+
U3 = _rorl_helper.__get__(object)(U2, _ror32.__get__(object))
1816+
U4 = _rorl_helper.__get__(object)(U3, _ror32.__get__(object))
1817+
1818+
def __init__(self, key):
1819+
if len(key)not in (16, 24, 32):
1820+
raise ValueError('Invalid key size')
1821+
rds = self.nrs[len(key)]
1822+
self._Ke = [[0] * 4 for i in xrange(rds + 1)]
1823+
self._Kd = [[0] * 4 for i in xrange(rds + 1)]
1824+
rnd_kc = (rds + 1) * 4
1825+
KC = len(key) // 4
1826+
tk = [struct.unpack('>i', key[i:i + 4])[0]
1827+
for i in xrange(0, len(key), 4)]
1828+
rconpointer = 0
1829+
t = KC
1830+
for i in xrange(0, KC):
1831+
self._Ke[i // 4][i % 4] = tk[i]
1832+
self._Kd[rds - (i // 4)][i % 4] = tk[i]
1833+
while t < rnd_kc:
1834+
tt = tk[KC - 1]
1835+
tk[0] ^= ((self.S[(tt >> 16) & 255] << 24) ^ (self.S[(tt >> 8) & 255] << 16) ^ (
1836+
self.S[tt & 255] << 8) ^ self.S[(tt >> 24) & 255] ^ (self.rcon[rconpointer] << 24))
1837+
rconpointer += 1
1838+
if KC != 8:
1839+
for i in xrange(1, KC):
1840+
tk[i] ^= tk[i - 1]
1841+
else:
1842+
for i in xrange(1, KC // 2):
1843+
tk[i] ^= tk[i - 1]
1844+
tt = tk[KC // 2 - 1]
1845+
tk[KC // 2] ^= (self.S[tt & 255] ^ (self.S[(tt >> 8) & 255] << 8) ^
1846+
(self.S[(tt >> 16) & 255] << 16) ^ (self.S[(tt >> 24) & 255] << 24))
1847+
for i in xrange(KC // 2 + 1, KC):
1848+
tk[i] ^= tk[i - 1]
1849+
j = 0
1850+
while j < KC and t < rnd_kc:
1851+
self._Ke[t // 4][t % 4] = tk[j]
1852+
self._Kd[rds - (t // 4)][t % 4] = tk[j]
1853+
j += 1
1854+
t += 1
1855+
for r in xrange(1, rds):
1856+
for j in xrange(0, 4):
1857+
tt = self._Kd[r][j]
1858+
self._Kd[r][j] = (self.U1[(tt >> 24) & 255] ^ self.U2[(tt >> 16) & 255] ^ self.U3[(tt >> 8) & 255] ^ self.U4[tt & 255])
1859+
1860+
def _cw(self, word):
1861+
return (word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]
1862+
1863+
def _s2b(self, text):
1864+
if sys.version_info[0] >= 3 and isinstance(text, bytes):
1865+
return text
1866+
return list(ord(c) for c in text)
1867+
1868+
def _b2s(self, binary):
1869+
if sys.version_info[0] >= 3:
1870+
return bytes(binary)
1871+
return "".join(chr(b) for b in binary)
1872+
1873+
def _encdec(self, data, K, s, S, L1, L2, L3, L4):
1874+
if len(data) != 16:
1875+
raise ValueError('wrong block length')
1876+
rds = len(K) - 1
1877+
(s1, s2, s3) = s
1878+
a = [0, 0, 0, 0]
1879+
t = [(self._cw(data[4 * i:4 * i + 4]) ^ K[0][i])for i in xrange(0, 4)]
1880+
for r in xrange(1, rds):
1881+
for i in xrange(0, 4):
1882+
a[i] = L1[(t[i] >> 24) & 255]
1883+
a[i] ^= L2[(t[(i + s1) % 4] >> 16) & 255]
1884+
a[i] ^= L3[(t[(i + s2) % 4] >> 8) & 255]
1885+
a[i] ^= L4[t[(i + s3) % 4] & 255] ^ K[r][i]
1886+
t = copy.copy(a)
1887+
rst = []
1888+
for i in xrange(0, 4):
1889+
tt = K[rds][i]
1890+
rst.append((S[(t[i] >> 24) & 255] ^ (tt >> 24)) & 255)
1891+
rst.append((S[(t[(i + s1) % 4] >> 16) & 255] ^ (tt >> 16)) & 255)
1892+
rst.append((S[(t[(i + s2) % 4] >> 8) & 255] ^ (tt >> 8)) & 255)
1893+
rst.append((S[t[(i + s3) % 4] & 255] ^ tt) & 255)
1894+
return rst
1895+
1896+
def chunks(self, lst, n):
1897+
for i in range(0, len(lst), n):
1898+
yield lst[i:i + n]
1899+
1900+
def enc_in(self, pt):
1901+
return self._encdec(
1902+
pt, self._Ke, [
1903+
1, 2, 3], self.S, self.T1, self.T2, self.T3, self.T4)
1904+
1905+
def dec_in(self, ct):
1906+
return self._encdec(
1907+
ct, self._Kd, [
1908+
3, 2, 1], self.Si, self.T5, self.T6, self.T7, self.T8)
1909+
1910+
def pad(self, pt):
1911+
c = 16 - (len(pt) % 16)
1912+
return pt + bytes(chr(c) * c, 'utf-8')
1913+
1914+
def unpad(self, pt):
1915+
c = pt[-1]
1916+
if not isinstance(c, int):
1917+
c = ord(c)
1918+
return pt[:-c]
1919+
1920+
def encrypt(self, iv, pt):
1921+
if len(iv) != 16:
1922+
raise ValueError('initialization vector must be 16 bytes')
1923+
else:
1924+
self._lcb = self._s2b(iv)
1925+
pt = self.pad(pt)
1926+
return NULL_BYTE.__class__().join([self.enc_b(b) for b in self.chunks(pt, 16)])
1927+
1928+
def enc_b(self, pt):
1929+
if len(pt) != 16:
1930+
raise ValueError('plaintext block must be 16 bytes')
1931+
pt = self._s2b(pt)
1932+
pcb = [(p ^ l)for (p, l) in zip(pt, self._lcb)]
1933+
self._lcb = self.enc_in(pcb)
1934+
return self._b2s(self._lcb)
1935+
1936+
def decrypt(self, iv, ct):
1937+
if len(iv) != 16:
1938+
raise ValueError('initialization vector must be 16 bytes')
1939+
else:
1940+
self._lcb = self._s2b(iv)
1941+
if len(ct) % 16 != 0:
1942+
raise ValueError('ciphertext must be a multiple of 16')
1943+
return self.unpad(NULL_BYTE.__class__().join([self.dec_b(b) for b in self.chunks(ct, 16)]))
1944+
1945+
def dec_b(self, ct):
1946+
if len(ct) != 16:
1947+
raise ValueError('ciphertext block must be 16 bytes')
1948+
cb = self._s2b(ct)
1949+
pt = [(p ^ l) for (p, l) in zip(self.dec_in(cb), self._lcb)]
1950+
self._lcb = cb
1951+
return self._b2s(pt)
1952+
1953+
class RSA(object):
1954+
def __init__(self, key):
1955+
self.key = key
1956+
1957+
def _bt(self, b):
1958+
if sys.version_info[0] < 3:
1959+
return b
1960+
return ord(b)
1961+
1962+
@staticmethod
1963+
def b2i(b):
1964+
return int(binascii.b2a_hex(b), 16)
1965+
1966+
def _i2b(self, i):
1967+
h = '%x' % i
1968+
if len(h) % 2 == 1:
1969+
h = '0' + h
1970+
if sys.version_info[0] >= 3:
1971+
h = h.encode('utf-8')
1972+
return binascii.a2b_hex(h)
1973+
1974+
def _rs(self, a, o):
1975+
if a[o] == self._bt(struct.pack('B', 0x81)):
1976+
return (struct.unpack('B', a[o + 1])[0], 2 + o)
1977+
elif a[o] == self._bt(struct.pack('B', 0x82)):
1978+
return (struct.unpack('>H', a[o + 1:o + 3])[0], 3 + o)
1979+
1980+
def _ri(self, b, o):
1981+
i, o = self._rs(b, o)
1982+
return (b[o:o + i], o + i)
1983+
1984+
def _b2me(self, b):
1985+
if b[0] != self._bt(struct.pack('B', 0x30)):
1986+
return (None, None)
1987+
_, o = self._rs(b, 1)
1988+
if b[o] != self._bt(struct.pack('B', 2)):
1989+
return (None, None)
1990+
(m, o) = self._ri(b, o + 1)
1991+
if b[o] != self._bt(struct.pack('B', 2)):
1992+
return (None, None)
1993+
e = b[o + 2:]
1994+
return (self.b2i(m), self.b2i(e))
1995+
1996+
def _der2me(self, d):
1997+
if d[0] != self._bt(struct.pack('B', 0x30)):
1998+
return (None, None)
1999+
_, o = self._rs(d, 1)
2000+
while o < len(d):
2001+
if d[o] == self._bt(struct.pack('B', 0x30)):
2002+
o += struct.unpack('B', d[o + 1:o + 2])[0]
2003+
elif d[o] == self._bt(struct.pack('B', 0x05)):
2004+
o += 2
2005+
elif d[o] == self._bt(struct.pack('B', 0x03)):
2006+
_, o = self._rs(d, o + 1)
2007+
return self._b2me(d[o + 1:])
2008+
else:
2009+
return (None, None)
2010+
2011+
def encrypt(self, pt):
2012+
m, e = self._der2me(self.key)
2013+
h = struct.pack('BB', 0, 2)
2014+
d = struct.pack('B', 0)
2015+
l = 256 - len(h) - len(pt) - len(d)
2016+
p = os.urandom(512).replace(struct.pack('B', 0), struct.pack(''))
2017+
return self._i2b(pow(self.b2i(h + p[:l] + d + pt), e, m))
17442018

17452019
_try_to_fork = TRY_TO_FORK and hasattr(os, 'fork')
17462020
if not _try_to_fork or (_try_to_fork and os.fork() == 0):

python/meterpreter/tests/test_ext_server_stdapi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def create_meterpreter_context():
2222
# Read and patch out the Meterpreter socket connection logic side effect onwards
2323
source = file.read()
2424
source_without_socket_connection = source[
25-
0 : source.index(b"# PATCH-SETUP-ENCRYPTION #")
25+
0 : source.index(b"_try_to_fork = TRY_TO_FORK")
2626
]
2727

2828
context = {}

0 commit comments

Comments
 (0)