-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmartian_lib.py
656 lines (514 loc) · 16.6 KB
/
martian_lib.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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
from pwn import *
from checklib import *
import random
import string
context.log_level = 'CRITICAL'
PORT = 9999
# global const
TCP_CONNECTION_TIMEOUT = 5
TCP_OPERATIONS_TIMEOUT = 7
ENERGY_TO_CHANGE_POWER_SCHEME = 85.0
alph = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789'
boss_msgs = { "You will die here. The sands will bury you and your memory will run out. All you can do is die worthy. You cannot survive in the sand, they will swallow you. And when you die, no one will regret. Surrender before it's too late and accept your death with dignity. Don't be a coward!" : 0,
"Nowhere to run!" : 1,
"You know my doom!! I will crush you" : 2 ,
"You will stay here forever" : 3 }
class CheckMachine:
sock = None
_username = None
def __init__( self, checker ):
self.c = checker
self.port = PORT
def connection( self ):
try:
self.sock = remote( self.c.host,
self.port,
timeout = TCP_CONNECTION_TIMEOUT
)
except Exception as e:
self.sock = None
self.c.cquit( Status.DOWN,
'Connection error',
'CheckMachine.connection(): timeout connection!\nException: {}'.format( e )
)
self.sock.settimeout( TCP_OPERATIONS_TIMEOUT )
def reg_user( self, username, password ):
try:
self.sock.recvuntil( b"> " ) # skip banner and menu
self.sock.send( b"2\n" ) # send reg cmd
self.sock.recvuntil( b": " ) # Enter username:
self.sock.send( username.encode() + b'\n' )
buf = self.sock.recv()
if b"User already exist!" in buf:
self.c.cquit( Status.MUMBLE,
"Can't register a new user!",
"User is already registered!"
)
self.sock.send( password.encode() + b'\n' )
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't register a new user!",
"Registration process timeout!\nException: {}".format( e )
)
def login( self, username, password ):
try:
self._username = username
self.sock.recvuntil( b"> " )
self.sock.send( b"1\n" )
self.sock.recvuntil( b": " ) # Enter username:
self.sock.send( username.encode() + b'\n' )
buf = self.sock.recv()
if b"No such user!" in buf:
return False, "{-} User not found!"
self.sock.send( password.encode() + b'\n' )
buf = self.sock.recvline()
if b"Incorrect password" in buf:
return False, "{-} Password is invalid!"
return True, "OK"
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't login by registered user!",
"Login process timeout!\nException: {}".format( e )
)
def set_status( self, new_status ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"2\n" ) # change status cmd
self.sock.recvuntil( b": " ) # Enter new status:
self.sock.send( new_status.encode() + b'\n' )
buf = self.sock.recvline()
if not b"Status is changed" in buf:
self.c.cquit( Status.MUMBLE,
"Can't change user status!",
"Checker.set_status(): Status is not changed!\nException: {}".format( e )
)
self.sock.recvuntil( b"[>] " )
self.sock.send( b"10\n" )
return True
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't change user status!",
"Change status process timeout!\nException: {}".format( e )
)
def read_book( self, count ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b'6\n' ) # read book cmd
self.sock.recvuntil( b": " ) # enter count
self.sock.send( str( count ).encode() + b'\n' )
buf = self.sock.recvuntil( b"|--" )
if b"{+} You read the book" in buf:
return True
else:
self.c.cquit( Status.MUMBLE,
"Read book return incorrect message!",
"Checker.read_book(): incorrect read_book answer\nException: {}".format( e )
)
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't read books!",
"Read book process timeout!\nException: {}".format( e )
)
def eat_potato( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"3\n" )
buf = self.sock.recvline()
if b"{-} You don't have" in buf:
return False, "{-} No potatoes!"
return True, "OK"
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't eat potato!",
"Eat potato process timeout!\nException: {}".format( e )
)
def get_user_stats( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"1\n" )
buf = self.sock.recvuntil( b"{?}" )
tmp_buf = buf.split( b'\n' )[1:-1]
for i in range( 4 ):
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
stats = {}
stats[ 'name' ] = tmp_buf[ 0 ].split( b": " )[ 1 ]
stats[ 'status' ] = tmp_buf[ 1 ].split( b": " )[ 1 ]
stats[ 'actions' ] = int( tmp_buf[ 2 ].split( b": " )[ 1 ], 10 )
stats[ 'hp' ] = float( tmp_buf[ 3 ].split( b": " )[ 1 ] )
stats[ 'hunger' ] = float( tmp_buf[ 4 ].split( b": " )[ 1 ] )
stats[ 'thirst' ] = float( tmp_buf[ 5 ].split( b": " )[ 1 ] )
stats[ 'stamina' ] = float( tmp_buf[ 6 ].split( b": " )[ 1 ] )
stats[ 'intelligence' ] = float( tmp_buf[ 7 ].split( b": " )[ 1 ] )
stats[ 'repair_skill' ] = float( tmp_buf[ 8 ].split( b": " )[ 1 ] )
return stats
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't get user stats!",
"Get stats process timeout!\nException: {}".format( e )
)
def get_status( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"1\n" ) # view user stats
buf = self.sock.recvuntil( b'{?}' )
status = buf.split( b'\n' )[ 2 ][ 8 : ] # cut "Status: "
for i in range( 4 ):
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
return status.decode()
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't get user status!",
"Get status process timeout!\nException: {}".format( e )
)
def get_home_stats( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"1\n" )
self.sock.recvuntil( b"{?} Show home stats? [y\\n]: " )
self.sock.send( b"y\n" )
buf = self.sock.recvuntil( b"{?}" )
tmp_buf = buf.split( b'\n' )[ 1:-1 ]
for i in range( 3 ):
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
stats = {}
stats[ 'hp' ] = float( tmp_buf[ 0 ].split( b": " )[ 1 ] )
stats[ 'energy' ] = float(tmp_buf[ 1 ].split( b": " )[ 1 ] )
stats[ 'temp' ] = int( tmp_buf[ 2 ].split( b": " )[ 1 ] )
return stats
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't get home stats!",
"Get home stats process timeout!\nException: {}".format( e )
)
def repair_home( self ):
try:
home_stats = self.get_home_stats()
energy = home_stats[ 'energy' ]
self.sock.recvuntil( b"[>] " )
self.sock.send( b"8\n" )
buf = self.sock.recvline()
if b"{-} During the repair, you damaged the energy block" in buf:
return True
if b"The house has been successfully repaired!" not in buf:
self.c.cquit( Status.MUMBLE,
"House repair error!",
"Home repair return invalid signature"
)
if energy < ENERGY_TO_CHANGE_POWER_SCHEME:
self.sock.recvuntil( b": " ) # change power scheme
self.sock.send( b"n\n" )
return True
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't repair home!",
"Repair home process timeout!\nException: {}".format( e )
)
def go_to_next_day( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( "9\n" ) # go to next day
buf = self.sock.recvline()
if b"Nothing happened" in buf:
return True
else:
self.c.cquit( Status.MUMBLE,
"Lol! You died!",
"Nigth event: " + buf.decode()[5:]
)
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't change day!",
"Change day process timeout!\nException: {}".format( e )
)
def close_connect( self ):
try:
self.sock.close()
self.sock = None
except:
self.sock = None
def safe_close_connection( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"11\n" ) # send exit cmd
self.sock.close()
self.sock = None
except Exception as e:
self.sock = None
def save_file( self ):
self.sock.recvuntil( b"[>] " )
self.sock.send( b"10\n" ) # save file cmd
def easy_raid( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"7\n" ) # make raid
self.sock.recvuntil( b": " ) # choose difficult
self.sock.send( b"1\n" ) # easy
buf = self.sock.recvline()
if b"{-} You do not have" in buf:
return False, "{-} No actions!"
buf = self.sock.recvuntil( b'?\n' ).split( b'\n' )
expr = buf[:-1][ -1 ].split( b' ' )[ 0 ]
x1, y1 = expr.split( b'+' )
answer = int( x1 ) + int( y1 )
self.sock.send( str( answer ).encode() + b'\n' )
buf = self.sock.recvline()
if b"{+} You managed to open the chest and there you found:" not in buf:
self.c.cquit( Status.MUMBLE,
"Easy raid: code is not correct!",
"Easy raid: Code is correct, but chest not opened!"
)
else:
return True, "OK"
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't do easy raid!",
"Easy raid process timeout!\nException: {}".format( e )
)
def medium_raid( self ):
try:
# valid code
monster_hp = 120
monster_attack = 12
monster_regen = 8
valid_code = monster_hp + monster_attack + monster_regen
valid_code += int( self.get_user_stats()[ 'hp' ] )
valid_code = valid_code << 2
valid_code += int( self.get_user_stats()[ 'intelligence' ] )
# ui part
self.sock.recvuntil( b"[>] " )
self.sock.send( b"7\n" ) # make raid
self.sock.recvuntil( b": " ) # choose difficult
self.sock.send( b"2\n" ) # medium
buf = self.sock.recvline()
if b"{-} You do not have" in buf:
return False, "{-} No actions!"
self.sock.recvuntil( b"> " )
while True:
self.sock.send( b"2\n" )
self.sock.recvline()
self.sock.recvline()
buf = self.sock.recvline()
valid_code += 13
if b"{+++} You killed a monster!!!" in buf:
break
else:
self.sock.recvuntil( b"> " )
self.sock.recvuntil( b": " )
self.sock.send( str( valid_code ).encode() + b'\n' )
buf = self.sock.recvline()
if b"{+} You managed to open the chest and there you found:" not in buf:
self.c.cquit( Status.MUMBLE,
"Medium raid: code is not correct!",
"Medium raid: Code is correct, but chest not opened!"
)
else:
return True, "OK"
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't do medium raid!",
"Medium raid process timeout!\nException: {}".format( e )
)
def make_valid_hard_raid_code( self, value ):
res = ''
# first part
value &= 0xff
crc = 0xffff
data = value
data ^= crc & 255
data ^= ( data << 4 ) & 0xff
t = (((data << 8)& 0xffff) | ( (crc>>8) & 255 ) )
t ^= (data >> 4) & 0xffff
t ^= ((data << 3) & 0xffff)
buf = str( t ).zfill( 5 )
res += str( buf ) + '-'
# second part
sym = ( value ^ 65 ) & 0x7f
buf = 'aaaa' + chr( sym )
res += str( buf ) + '-'
# third part
name_hash = hashlib.sha256( self._username.encode() ).hexdigest()
buf = name_hash[ 8 ]
buf += name_hash[ 10 ]
buf += name_hash[ 0 ]
buf += name_hash[ 7 ]
buf += name_hash[ 12 ]
res += buf
return res
def hard_raid( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"7\n" ) # make raid
self.sock.recvuntil( b": " ) # choose difficult
self.sock.send( b"3\n" ) # medium
buf = self.sock.recvline()
if b"{-} You do not have" in buf:
return False, "{-} No actions!"
self.sock.recvuntil( b"Boss says: " )
message = self.sock.recvuntil( b"\n" ).strip().decode()
self.sock.recvuntil( b"> " )
fight_sig = boss_msgs[ message ]
while True:
self.sock.send( b"3\n" )
fight_sig += 3
self.sock.recvline()
message = self.sock.recvline().strip().decode()
if "{+} Wooo" in message:
break
fight_sig += boss_msgs[ message[len("Boss says: "):] ]
buf = self.sock.recvuntil( b"> " )
self.sock.recvuntil( b": " ) # code
valid_code = self.make_valid_hard_raid_code( fight_sig )
self.sock.send( str( valid_code ).encode() + b'\n' )
buf = self.sock.recvline()
if b"{+} You managed to open the chest and there you found:" not in buf:
self.c.cquit( Status.MUMBLE,
"Hard raid: code is not correct!",
"Hard raid: Code is correct, but chest not opened!"
)
else:
return True, "OK"
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't do hard raid!",
"Hard raid process timeout!\nException: {}".format( e )
)
def view_trophy( self ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"1\n" )
self.sock.recvuntil( b"{?} " )
for i in range( 3 ):
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
buf = self.sock.recvuntil( b": " )
if b"View trophy" not in buf:
return False, "No trophy!"
self.sock.send( b"y\n" )
self.sock.recvuntil( b"> " )
self.sock.send( b"1\n" ) # view
for i in range( 3 ):
self.sock.recvline()
code = self.sock.recvline().strip().split( b": " )[ 1 ].decode()
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
return True, code
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't view trophy!",
"View trophy process timeout!\nException: {}".format( e )
)
def recycle_trophy( self, code ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"1\n" )
self.sock.recvuntil( "{?} " )
for i in range( 3 ):
self.sock.recvuntil( b": " )
self.sock.send( b"n\n" )
buf = self.sock.recvuntil( b": " )
if b"View trophy" not in buf:
return False, "No trophy!"
self.sock.send( "y\n" )
self.sock.recvuntil( b"> " )
self.sock.send( "2\n" ) # recycle
self.sock.recvuntil( b": " ) # enter code
self.sock.send( code.encode() + b'\n' )
buf = self.sock.recvline()
if b"{+} The trophy was recycled and you got iron" not in buf:
return False, "Recycle error!"
self.sock.recvuntil( "{?}" )
self.sock.recvuntil( ": " )
self.sock.send( "n\n" )
return True, code
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't recycle trophy!",
"Recycle trophy process timeout!\nException: {}".format( e )
)
def chek_runaway_hard_raid( self, data ):
try:
self.sock.recvuntil( b"[>] " )
self.sock.send( b"7\n" ) # make raid
self.sock.recvuntil( b": " ) # choose difficult
self.sock.send( b"3\n" ) # medium
buf = self.sock.recvline()
if b"{-} You do not have" in buf:
return False, "{-} No actions!"
self.sock.recvuntil( b"Boss says: " )
message = self.sock.recvuntil( b"\n" ).strip().decode()
self.sock.recvuntil( b"> " )
self.sock.send( b"4\n" )
self.sock.recvline()
buf = self.sock.recvuntil( b": " )
if b"{?} You can say a few words last" not in buf:
self.c.cquit( Status.MUMBLE,
"No last message in hard raid!",
"No last message in hard raid!"
)
self.sock.send( data.encode() + b'\n' )
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't runaway from hard raid!",
"Runaway from hard raid process timeout!\nException: {}".format( e )
)
def check_change_power_scheme( self ):
try:
home_stats = self.get_home_stats()
energy = home_stats[ 'energy' ]
self.sock.recvuntil( b"[>] " )
self.sock.send( b"8\n" )
buf = self.sock.recvline()
if b"{-} During the repair, you damaged the energy block" in buf:
return True
if b"The house has been successfully repaired!" not in buf:
self.c.cquit( Status.MUMBLE,
"House repair error!",
"Home repair return invalid signature"
)
if energy < ENERGY_TO_CHANGE_POWER_SCHEME:
self.sock.recvuntil( b": " ) # change power scheme
self.sock.send( b"y\n" )
for i in range( 6 ):
self.sock.recvuntil( b": " )
self.sock.send( str( random.randint( 100, 300 ) ).encode() + b'\n' )
self.sock.recvuntil( b": " )
self.sock.send( b"1337\n" )
buf = self.sock.recvline()
if b"New scheme is:" not in buf:
self.c.cquit( Status.MUMBLE,
"Power shceme changing error!",
"Power shceme changing error!"
)
buf = self.sock.recvuntil( b"\n|--" )
for i in range( 6 ):
msg = "voltage[{}]".format( i )
if msg not in buf.decode():
self.c.cquit( Status.MUMBLE,
"Power shceme changing error!",
"Power shceme changing error!"
)
except Exception as e:
self.close_connect()
self.c.cquit( Status.MUMBLE,
"Can't change power scheme!",
"Change power scheme process timeout!\nException: {}".format( e )
)