这题作为VM还是很简单的,主要时间都在去混淆上了。
拿到pyc,在线反汇编一下:
佤 = 0
侰 = ~佤 * ~佤
俴 = 侰 + 侰
def 䯂(䵦):
굴 = 佤
굿 = 佤
괠 = [佤] * 俴 ** (俴 * 俴)
궓 = [佤] * 100
괣 = []
while 䵦[굴][佤] != "듃":
굸 = 䵦[굴][佤].lower()
亀 = 䵦[굴][侰:]
if 굸 == "뉃":
괠[亀[佤]] = 괠[亀[侰]] + 괠[亀[俴]]
elif 굸 == "렀":
괠[亀[佤]] = 괠[亀[侰]] ^ 괠[亀[俴]]
elif 굸 == "렳":
괠[亀[佤]] = 괠[亀[侰]] - 괠[亀[俴]]
elif 굸 == "냃":
괠[亀[佤]] = 괠[亀[侰]] * 괠[亀[俴]]
elif 굸 == "뢯":
괠[亀[佤]] = 괠[亀[侰]] / 괠[亀[俴]]
elif 굸 == "륇":
괠[亀[佤]] = 괠[亀[侰]] & 괠[亀[俴]]
elif 굸 == "맳":
괠[亀[佤]] = 괠[亀[侰]] | 괠[亀[俴]]
elif 굸 == "괡":
괠[亀[佤]] = 괠[亀[佤]]
elif 굸 == "뫇":
괠[亀[佤]] = 괠[亀[侰]]
elif 굸 == "꼖":
괠[亀[佤]] = 亀[侰]
elif 굸 == "뫻":
궓[亀[佤]] = 괠[亀[侰]]
elif 굸 == "딓":
괠[亀[佤]] = 궓[亀[侰]]
elif 굸 == "댒":
괠[亀[佤]] = 佤
elif 굸 == "묇":
궓[亀[佤]] = 佤
elif 굸 == "묟":
괠[亀[佤]] = input(괠[亀[侰]])
elif 굸 == "꽺":
궓[亀[佤]] = input(괠[亀[侰]])
elif 굸 == "돯":
print(괠[亀[佤]])
elif 굸 == "뭗":
print(궓[亀[佤]])
elif 굸 == "뭿":
굴 = 괠[亀[佤]]
elif 굸 == "뮓":
굴 = 궓[亀[佤]]
elif 굸 == "뮳":
굴 = 괣.pop()
elif 굸 == "믃" or 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 亀[佤]
괣.append(굴)
continue
elif 굸 == "꽲":
괠[7] = 佤
for i in range(len(괠[亀[佤]])):
if 괠[亀[佤]] != 괠[亀[侰]]:
괠[7] = 侰
굴 = 괠[亀[俴]]
괣.append(굴)
elif 굸 == "꾮":
괢 = ""
for i in range(len(괠[亀[佤]])):
괢 += chr(ord(괠[亀[佤]][i]) ^ 괠[亀[侰]])
괠[亀[佤]] = 괢
elif 굸 == "꿚":
괢 = ""
for i in range(len(괠[亀[佤]])):
괢 += chr(ord(괠[亀[佤]][i]) - 괠[亀[侰]])
괠[亀[佤]] = 괢
elif 굸 == "떇" or 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 괠[亀[佤]]
괣.append(굴)
continue
elif 굸 == "뗋" or 괠[亀[侰]] > 괠[亀[俴]]:
굴 = 궓[亀[佤]]
괣.append(굴)
continue
elif 굸 == "똷" or 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 亀[佤]
괣.append(굴)
continue
elif 굸 == "뚫" or 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 괠[亀[佤]]
괣.append(굴)
continue
elif 굸 == "띇" and 괠[亀[侰]] == 괠[亀[俴]]:
굴 = 궓[亀[佤]]
괣.append(굴)
continue
굴 += 侰
䯂(
[
["꼖", 佤, "Authentication token: "],
["꽺", 佤, 佤],
[
"꼖",
6,
"á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ׿ÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜÉïÙãäãÖÓÕÙÛá×äÕà©â«³£ï²ÕÔÈ·±â¨ë",
],
["꼖", 俴, 俴 ** (3 * 俴 + 侰) - 俴 ** (俴 + 侰)],
["꼖", 4, 15],
["꼖", 3, 侰],
["냃", 俴, 俴, 3],
["뉃", 俴, 俴, 4],
["괡", 佤, 俴],
["댒", 3],
["꾮", 6, 3],
["꼖", 佤, "Thanks."],
["꼖", 侰, "Authorizing access..."],
["돯", 佤],
["딓", 佤, 佤],
["꾮", 佤, 俴],
["꿚", 佤, 4],
["꼖", 5, 19],
["꽲", 佤, 6, 5],
["돯", 侰],
["듃"],
["꼖", 侰, "Access denied!"],
["돯", 侰],
["듃"],
]
)
很明显这是加了替换反混淆,而且看形式非常像vm虚拟机(非常多的if、elif),我们根据这几个韩语(可能是)分别代表的功能,尝试着替换一下,
下面是初步替换的结果:
def vm(program):
i = 0
j = 0
reg1 = [0] * 16
reg2 = [0] * 100
stack = []
while program[i][0] != "end":
opcode = program[i][0].lower()
arr = program[i][1:]
if opcode == "add":
reg1[arr[0]] = reg1[arr[1]] + reg1[arr[2]]
elif opcode == "xor":
reg1[arr[0]] = reg1[arr[1]] ^ reg1[arr[2]]
elif opcode == "sub":
reg1[arr[0]] = reg1[arr[1]] - reg1[arr[2]]
elif opcode == "mul":
reg1[arr[0]] = reg1[arr[1]] * reg1[arr[2]]
elif opcode == "div":
reg1[arr[0]] = reg1[arr[1]] / reg1[arr[2]]
elif opcode == "and_":
reg1[arr[0]] = reg1[arr[1]] & reg1[arr[2]]
elif opcode == "or_":
reg1[arr[0]] = reg1[arr[1]] | reg1[arr[2]]
elif opcode == "mov1":
reg1[arr[0]] = reg1[arr[0]]
elif opcode == "mov2":
reg1[arr[0]] = reg1[arr[1]]
elif opcode == "move":
reg1[arr[0]] = arr[1]
elif opcode == "mov4":
reg2[arr[0]] = reg1[arr[1]]
elif opcode == "mov5":
reg1[arr[0]] = reg2[arr[1]]
elif opcode == "setz1":
reg1[arr[0]] = 0
elif opcode == "setz2":
reg2[arr[0]] = 0
elif opcode == "input1":
reg1[arr[0]] = input(reg1[arr[1]])
elif opcode == "input2":
reg2[arr[0]] = input(reg1[arr[1]])
elif opcode == "print1":
print(reg1[arr[0]])
elif opcode == "print2":
print(reg2[arr[0]])
elif opcode == "reg1_to_i":
i = reg1[arr[0]]
elif opcode == "reg2_to_i":
i = reg2[arr[0]]
elif opcode == "stack_to_i":
i = stack.pop()
elif opcode == "믃" or reg1[arr[1]] > reg1[arr[2]]:
i = arr[0]
stack.append(i)
continue
elif opcode == "꽲":
reg1[7] = 0
for i in range(len(reg1[arr[0]])):
if reg1[arr[0]] != reg1[arr[1]]:
reg1[7] = 1
i = reg1[arr[2]]
stack.append(i)
elif opcode == "Sum_xor":
str1 = ""
for i in range(len(reg1[arr[0]])):
str1 += chr(ord(reg1[arr[0]][i]) ^ reg1[arr[1]])
reg1[arr[0]] = str1
elif opcode == "Sum_gap":
str1 = ""
for i in range(len(reg1[arr[0]])):
str1 += chr(ord(reg1[arr[0]][i]) - reg1[arr[1]])
reg1[arr[0]] = str1
elif opcode == "떇" or reg1[arr[1]] > reg1[arr[2]]:
i = reg1[arr[0]]
stack.append(i)
continue
elif opcode == "뗋" or reg1[arr[1]] > reg1[arr[2]]:
i = reg2[arr[0]]
stack.append(i)
continue
elif opcode == "똷" or reg1[arr[1]] == reg1[arr[2]]:
i = arr[0]
stack.append(i)
continue
elif opcode == "뚫" or reg1[arr[1]] == reg1[arr[2]]:
i = reg1[arr[0]]
stack.append(i)
continue
elif opcode == "띇" and reg1[arr[1]] == reg1[arr[2]]:
i = reg2[arr[0]]
stack.append(i)
continue
i += 1
vm(
[
["move", 0, "Authentication token: "],
["input2", 0, 0]
["move", 6, "á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ׿ÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜÉïÙãäãÖÓÕÙÛá×äÕà©â«³£ï²ÕÔÈ·±â¨ë",],
["move", 2, 120],
["move", 4, 15],
["move", 3, 1],
["mul", 2, 2, 3],
["add", 2, 2, 4],
["mov1", 0, 2],
["setz1", 3],
["Sum_xor", 6, 3],
["move", 0, "Thanks."],
["move", 1, "Authorizing access..."],
["print1", 0],
["mov5", 0, 0],
["Sum_xor", 0, 2],
["Sum_gap", 0, 4],
["move", 5, 19],
["꽲", 0, 6, 5],
["print1", 1],
["end"],
["move", 1, "Access denied!"],
["print1", 1],
["end"],
]
)
有部分字符还没有替换,用到时候再看一下,
那么下面的数组内容就是伪汇编了,
下一步是尝试从这里简单反汇编一下:
vm(
[
["move", 0, "Authentication token: "],
["input2", 0, 0] # reg2[0] = input("Authentication token: ")
["move", 6, "á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ׿ÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜÉïÙãäãÖÓÕÙÛá×äÕà©â«³£ï²ÕÔÈ·±â¨ë",],
# reg1[6] = "á×äÓâ..."
["move", 2, 120], # reg1[2] = 120
["move", 4, 15], # reg1[4] = 15
["move", 3, 1], # reg1[3] = 1
["mul", 2, 2, 3], # reg1[2] = reg1[2] * reg1[3] = 120
["add", 2, 2, 4], # reg1[2] = reg1[2] + reg1[4] = 135
["mov1", 0, 2], # reg1[0] = reg1[0]
["setz1", 3], # reg1[3] = 0
["Sum_xor", 6, 3], # reg1[6] = reg1[6][i] ^ reg1[3] -> reg1[6] ^= 0
["move", 0, "Thanks."],
#reg1[0] = "Thanks."
["move", 1, "Authorizing access..."],
#reg1[1] = "Authorizing access..."
["print1", 0], # print("Thanks.")
["mov5", 0, 0], # reg1[0] = reg2[0] = INPUT
["Sum_xor", 0, 2], # reg1[0] = reg1[0][i] ^ reg1[2] -> INPUT ^= 135
["Sum_gap", 0, 4], # reg1[0] = reg1[0][i] - reg1[4] -> reg1[0] -= 15
["move", 5, 19], # reg1[5] = 19
["check", 0, 6, 5], # INPUT == reg1[6] ? reg1[7] = 0 : reg1[7] = 1
["print1", 1], # print("Authorizing access...")
["end"], # end
["move", 1, "Access denied!"],
["print1", 1], # print("Access denied!")
["end"], # end
]
)
反汇编大概就是这样的,可以看到对input的操作就是减去了异或了135再减去15,,最后跟密文对照,直接写代码解密:
enc = "á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ׿ÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜÉïÙãäãÖÓÕÙÛá×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
for i in enc:
print(chr((ord(i) + 15) ^ 135), end = '')
flag很长:
watevr{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Standard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}