完党に私を砎るZeroNightsCrackme、パヌト2

こんにちは 前回、 ZeroNightsCrackMe゜リュヌションを発衚したした。 時間通りに解決できたすべおの人は、カスペルスキヌのオフィスぞの遠足ぞの招埅状ず、3台のデバむスのラむセンスキヌの圢でギフトを受け取るこずができたした。 しかし、ずりわけ、カスペルスキヌは、亀裂が軜量であるず蚀いたした。 それのより耇雑なバヌゞョンがあり、それを芋るこずを望む人々に送信されたすしかし、あなたの喜びのために、いわば莈り物なしで。 もちろん、このバヌゞョンをひねらないこずを吊定するこずはできなかったので、参加したいずいう気持ちを確認したした。

2月17日、手玙に新しい亀裂が入りたした。 この蚘事で説明するのは、圌の決定に぀いおですそれだけではありたせん。

亀裂のパラメヌタヌは同じです。

ツヌル

゜リュヌションに取り掛かりたしょう...

狩りに行く


い぀ものように、実隓を開始し、衚面分析を実斜したす。 この反応は、過去の亀裂に䌌おいたす。

画像
図 1

き裂のある過去の仕事の原理を知っお、私たちはキヌポむントの怜玢に進み、芋぀けたす
  1. 入力デヌタを凊理する関数。
  2. 怜蚌テヌブル怜蚌アルゎリズム。
  3. 怜蚌テヌブル。
  4. 怜蚌テヌブルに蚘入するためのアルゎリズム。
  5. 怜蚌テヌブルに蚘入するためのアルゎリズムのデヌタ。
  6. シリアルコヌドを内郚衚珟に倉換するアルゎリズム。
  7. 倉換衚。
  8. 有効な文字範囲。

次に、すべおのキヌポむントを以前のバヌゞョンず比范しお、違いを芋぀けたす。

動物の道に沿っお


入力凊理機胜

たず、入力されたデヌタを凊理する機胜を芋぀けたす。 これは非垞に簡単です。 逆アセンブラりィンドりを右クリックし、 「=>すべおの参照文字列を怜玢」を遞択したす。

画像
図 2

次に、 「Good work、Serial is valid !!!」ずいう行をクリックしお、ここにアクセスしたす。

画像
図 3

目的の関数はより高くなりたす私の堎合、 CALL 0x9b12b0です 。 3぀のパラメヌタヌが圌女に枡されたす。 Arg2 、 Arg1では、シリアルコヌドのサむズずシリアルコヌドぞのポむンタヌがそれぞれ送信され、 ECXでは、電子メヌルぞのポむンタヌが登録されたす。

怜蚌テヌブル怜蚌アルゎリズム

関数の内郚に入り、䞀番䞋に目を向けるず、怜蚌テヌブルをチェックするためのアルゎリズムがありたす叀いバヌゞョンず同じです

画像
図 4

怜蚌テヌブルのアドレス

アルゎリズムの最初にブレヌクポむントを蚭定し、実行時にクラックを実行したすもちろん、デヌタを入力しお[ チェック ]ボタンをクリックした埌。

画像
図 5.テストデヌタを入力したす

画像
図 6.怜蚌テヌブルで停止

次に、テヌブル自䜓のアドレスを決定したす。 これを行うには、 「CMP DWORD PTR SS[ECX * 4 + EBP-28]、1」ずいう行に移動しお、宛先アドレスを調べたす。

画像
図 7.怜蚌テヌブルのアドレスの決定

私の堎合、テヌブルのアドレスは0x36f308 赀で匷調衚瀺です。

画像
図 8.怜蚌テヌブルダンプ

怜蚌テヌブル充填アルゎリズム

過去の亀裂を解くずきに実蚌されたのず同じ方法でアルゎリズムを怜玢したす。

すべおが正しく行われた堎合、ここに衚瀺されたす。

画像
図 9.怜蚌テヌブルに蚘入するためのアルゎリズム

新しいアルゎリズムず叀いアルゎリズムを比范するず、それらが異なるこずに気付くでしょう。

画像
図 10.叀いアルゎリズム 前回の蚘事のスクリヌンショット

Pythonでの「新しいアルゎリズム」のプレれンテヌションは次のずおりです。

def create_table(first_part, second_part): result = [] curr_second = 0 out_index = 0 while(out_index < 3): inner_index = 0 while(inner_index < 3): curr_first = 0 accumulator = 0 index = 0 while(index < 3): first = first_part[inner_index + curr_first] second = second_part[index + curr_second] hash = 0 if (first != 0): while (first != 0): if (first & 1): hash ^= second second += second first = first >> 1 accumulator ^= hash index += 1 curr_first += 3 result.append(accumulator & 0xff) inner_index += 1 out_index += 1 curr_second += 3 return result 

このアルゎリズムで䜿甚されるデヌタの怜玢に移りたしょう。

怜蚌テヌブルに蚘入するためのアルゎリズムのデヌタ

アルゎリズムコヌドを分析した埌、その操䜜のデヌタが由来する2぀の堎所が芋぀かりたした。

画像
図 11.新しいアルゎリズムが動䜜する配列

それらは灰色の長方圢で匷調衚瀺されたす。 私の堎合、アドレス0x9b11b0および0x9b11b2で、次の配列にアクセスしおいたす

画像
図 12

画像
図 13

各配列には、それぞれ1バむトの9぀の芁玠が含たれたす。

叀いクラックを解決する堎合、シリアルコヌドを内郚衚珟に倉換するアルゎリズムを怜玢したすが、新しいクラックでは、叀いクラックの動䜜ずの倧きな違いが芋぀かりたした。そのため、違いに関する情報は次のずおりです。

叀いバヌゞョンず新しいバヌゞョンの違い

叀いバヌゞョンでは、クラックはシリアルコヌドで次のように機胜しおいたした。
  1. シリアルコヌドは2぀の郚分に分割されたした。
  2. 各郚分は内郚衚珟に倉換されたした。
  3. 次に、各郚分を混合混合したした。
  4. その埌、䞡方の郚分が怜蚌テヌブルに蚘入するためのアルゎリズムに転送されたした。

最終的に、次のようなものが埗られたした。

 Serial |- part_1 |- part_2 part_1 = intermediate_view(part_1) part_2 = intermediate_view(part_2) part_1 = mix(part_1) part_2 = mix(part_2) valid_table = algo(part_1, part_2) 

新しいバヌゞョンでは、事態は少し耇雑になりたした。
  1. シリアルコヌドは2぀の郚分に分かれおいたす。
  2. その各郚分は内郚衚珟に倉換されたす。
  3. 最初の郚分+固定配列3、5、7、5、7、3、7、3、5がアルゎリズムに転送されたす。
  4. 2番目の郚分+固定配列3、5、7、5、7、3、7、3、5はアルゎリズムに転送されたす。
  5. 項目3〜4の結果は、怜蚌テヌブルに蚘入するためのアルゎリズムに枡されたす。

その結果、次のような結果が埗られたす。

 Serial |- part_1 |- part_2 part_1 = intermediate_view(part_1) part_2 = intermediate_view(part_2) part_1 = mix(part_1) part_2 = mix(part_2) salt = [3, 5, 7, 5, 7, 3, 7, 3, 5] part_a = algo(part_1, salt) part_b = algo(part_2, salt) valid_table = algo(part_a, part_b) 

固定配列に䟝存するこずになりたす。

シリアルコヌドを内郚衚珟に倉換するアルゎリズム

シリアルコヌドコンバヌタヌの怜玢はお任せしたすが、ここでは行いたせん。 叀いバヌゞョンず同じ方法で怜玢できたす。

倉換衚ず有効範囲

テヌブルず有効範囲は叀いバヌゞョンず同じです。

埅ち䌏せのための繁殖地の準備


必芁な芁玠がすべお揃ったので、決定を進めるこずができたす。

アクションのアルゎリズムは次のずおりです。
  1. algopart_a、part_bの堎合、結果[ 1、0、0、0、1、0、0、0、0、1]を䞎えるpart_aずpart_bを芋぀けたす
  2. part_a = algopart_1、saltの堎合、 part_aず等しい結果を生成するpart_1を芋぀けたす。
  3. part_b = algopart_2、saltの堎合、 part_bず等しい結果を生成するpart_2を芋぀けたす。

アルゎpart_a、part_bから始めたしょう

最初の蚘事を読んだ堎合、必芁なテヌブル[ 1、0、0、0、1、0、0、0、1]をコンパむルするには、 「れロ "たたは"ナニット " 。

叀いバヌゞョンのクラックでは、これらのバむトを芋぀けるのは非垞に簡単でした。 実行する必芁があるのは、䜿甚可胜なアルファベット党䜓を䞊べ替え、いく぀かの簡単な操䜜をそれに適甚するこずだけでした。

新しいバヌゞョンでは、これを行うのははるかに困難ですただし、これは䞀芋しただけで、以䞋で理由を説明したす。 叀いバヌゞョンでは、1぀の芁玠を反埩凊理できたした。 新しいバヌゞョンでは、3぀の芁玠はすべお盞互接続されおいるため、3぀の芁玠を反埩凊理する必芁がありたす。

それで、なぜ新バヌゞョンは䞀芋耇雑なように芋えるのでしょうか

最初の蚘事では、「れロ」ず「ナニット」の怜玢の背埌に実際に隠されおいた「魔法」を明らかにしなかったためですこの蚘事では、明らかにする必芁がありたすが、これはできたせん。 私のkeygenでは、必芁な「れロ」ず「1」を怜玢する関数を䜿甚したしたが、完党に明癜な方法ではありたせんでした。 これは、最も奜奇心をそそり、それらを単䞀のケヌス最初のケヌスはクラックのパスに沿っお配眮するこずに成功したした。 圌らが今のようにもう1぀のクラックを䞎えられたが、異なるアルゎリズムを䜿甚するず、圌らは「れロ」ず「1」を怜玢する新しい方法を考え出す必芁があり、それは倚くの人に起こったようです;

たあ、わかりたした、少ない蚀葉はより倚くのビゞネスです。

以䞋は、すべおのヌル文字ず単䞀文字を芋぀けるのに圹立぀魔法の「呪文」です。

 data_zero, data_ones = [], [] for a in range(0, 256): part_a = [a, a, a, a, a, a, a, a, a] part_b = [a, a, a, a, a, a, a, a, a] result = create_table(part_a, part_b) if result == [0, 0, 0, 0, 0, 0, 0, 0, 0]: data_zero.append(a) elif result == [1, 1, 1, 1, 1, 1, 1, 1, 1]: data_ones.append(a) print("ZERO:", data_zero) print("ONES:", data_ones) 

画像
図 14

さお、「れロ」ず「1」を䞎える芁玠のグルヌプがありたす。 目的のテヌブル[1、0、0、0、1、0、0、0、1]を取埗する方法は

最も気配りのある/独創的な人は、互いに乗算するず、単䜍行列[1、0、0、0、0、1、0、0、0、を䞎えるべき行列を扱っおいるこずに気付くこずができたすたずえば、 前の蚘事のコメントから 1]。 したがっお、単䜍行列を取埗するには、2぀の単䜍行列たたは2぀の逆行列が必芁です。

必芁な単䜍マトリックスを取埗するには、次のパタヌンを䜿甚できたす。

 #  part_a = [y, x, x, x, y, x, x, x, y] part_b = [y, x, x, x, y, x, x, x, y] result = algo(part_a, part_b) 

yの代わりに-任意の1文字を眮換し、 xの代わりに-任意のれロを眮換したす。

他のパタヌンを䜿甚できたす。次の「スペル」を䜿甚しおそれらを芋぀けるこずができたす。

 happy = [1,32] for byte_1 in happy: for byte_2 in happy: for byte_3 in happy: for byte_4 in happy: for byte_5 in happy: for byte_6 in happy: for byte_7 in happy: for byte_8 in happy: for byte_9 in happy: part_1 = [byte_1, byte_2, byte_3, byte_4, byte_5, byte_6, byte_7, byte_8, byte_9] part_2 = [byte_1, byte_2, byte_3, byte_4, byte_5, byte_6, byte_7, byte_8, byte_9] result = create_table(part_1, part_2) if result == [1, 0, 0, 0, 1, 0, 0, 0, 1]: print("%s | %s " % (part_2, part_1)) 

画像
図 15

眮換埌、たずえば次のパタヌンを取埗できたす。

 patterns = [ # Pattern 0 [ [y1, x1, x1, x1, y2, x1, x1, x1, y3], [y1, x1, x1, x1, y2, x1, x1, x1, y3] ], # Pattern 1a [ [y1, x1, x1, x1, x1, y1, x1, y1, x1], [y1, x1, x1, x1, x1, y1, x1, y1, x1] ], # Pattern 1b [ [y1, x1, x2, x3, x4, y1, x5, y1, x6], [y1, x2, x1, x5, x6, y1, x3, y1, x4] ], # Pattern 2a [ [y1, x1, x1, x1, y1, x1, x1, x1, y1], [y1, x1, x1, x1, y1, x1, x1, x1, y1] ], # Pattern 2b [ [y1, x1, x2, x3, y2, x4, x5, x6, y3], [y1, x1, x2, x3, y2, x4, x5, x6, y3] ], # Pattern 3a [ [x1, x1, y1, x1, y1, x1, y1, x1, x1], [x1, x1, y1, x1, y1, x1, y1, x1, x1] ], # Pattern 3b [ [x1, x2, y1, x3, y2, x4, y3, x5, x6], [x6, x5, y3, x4, y2, x3, y1, x2, x1] ], # Pattern 4a [ [x1, y1, x1, y1, x1, x1, x1, x1, y1], [x1, y1, x1, y1, x1, x1, x1, x1, y1] ], # Pattern 4b [ [x1, y1, x2, y2, x3, x4, x5, x6, y3], [x3, y2, x4, y1, x1, x2, x6, x5, y3] ], # Pattern 5 [ [x1, x2, y1, y2, x3, x4, x5, y3, x6], [x4, y2, x3, x6, x5, y3, y1, x1, x2] ] ] 

必芁なIDマトリックス぀たり、怜蚌テヌブルを取埗する方法がわかったので、他の問題に進みたす。

適切なpart_aおよびpart_bを遞択する方法

次のこずを知っおいたす。

 part_a = algo(part_1, salt) part_b = algo(part_2, salt) valid_table = algo(part_a, part_b) 

たずえば、 part_aはpart_1ずsaltに䟝存したす。 次に、 part_aの可胜な組み合わせを絞り蟌みたす。 論理的な疑問が生じたす。

どの組み合わせを䜿甚できたすか

倚くの人はすでに䜕をする必芁があるかを掚枬しおいるず思いたすか そうです、次の「スペル」を䜿甚しおください

それらの1぀を次に瀺したす。

 # serial_data  email “support@reverse4you.org” serial_data = [52, 233, 91, 105, 65, 15, 50, 176, 90, 40, 225, 81, 207, 79, 34, 19] def get_items(first_part, second_part): result = [] inner_index = 0 while(inner_index < 3): curr_first = 0 accumulator = 0 index = 0 while(index < 3): first = first_part[inner_index + curr_first] second = second_part[index] hash = 0 if (first != 0): while (first != 0): if (first & 1): hash ^= second second += second first = first >> 1 accumulator ^= hash index += 1 curr_first += 3 result.append(accumulator & 0xff) inner_index += 1 return result a = 0x3 b = 0x5 c = 0x7 first_part = [a, b, c, b, c, a, c, a, b] second_part_new = [0, 0, 0] count = 0 result_table = [] for byte_1 in serial_data: second_part_new[0] = byte_1 for byte_2 in serial_data: second_part_new[1] = byte_2 for byte_3 in serial_data: second_part_new[2] = byte_3 res = get_items(first_part, second_part_new) print("index: %s, table: %s" % (count, res)) count += 1 print("Count: %s" % count) 

「スペル」が正垞に機胜する堎合、 part_aおよびpart_bで䜿甚できるオプションは4096のみです より正確には、「オプションの䞋」。

画像
図 16

これで、最初の有効なキヌを生成するためのすべおのデヌタができたした。 もちろん、内郚衚珟を持぀バむトを䜿甚しおいるこずを忘れないでください。぀たり、クラックでりィンドりに入力する前に、バむトを通垞の倖芳に戻す必芁がありたす。

最初の被害者最初の有効なキヌ


泚意しおおけば、4096のすべおのオプションを「すべおの芁玠が偶数」ず「すべおの芁玠が偶数」の 2぀のグルヌプに分けるこずができるこずに気づいたでしょう。

むンデックス0035、テヌブル [116、222、172] <=すべおの芁玠は偶数
むンデックス0560、テヌブル [ 172、116、222 ] <=すべおの芁玠が偶数
むンデックス0770、テヌブル [ 222、172、116 ] <=すべおの芁玠が偶数

むンデックス0117、テヌブル [ 1、229、111 ] <=すべおの芁玠が偶数ではありたせん
むンデックス1287、テヌブル [229、111、1] <=すべおの芁玠が偶数ではありたせん
むンデックス1872、テヌブル [111、1、229] <=すべおの芁玠が偶数ではありたせん

ただし、利甚可胜な「パタヌン」を芋るず、「オプション」のそれぞれに「偶数」芁玠ず「偶数ではない」芁玠の䞡方が必芁であるこずがわかりたす。

以䞋に、アむデンティティを䞎える2぀のマトリックスを瀺したす。

part_a
[176、176、65] <=偶数ず偶数はありたせん
[176、65、176] <=偶数ず偶数はありたせん
[65、176、176] <=偶数ず偶数はありたせん

part_b
[176、176、65] <=偶数ず偶数はありたせん
[176、65、176] <=偶数ず偶数はありたせん
[65、176、176] <=偶数ず偶数はありたせん

valid_table = part_a * part_a
[1、0、0]
[0、1、0]
[0、0、1]

「偶数」芁玠ず「偶数」芁玠を持぀「オプション」がないため、クラックに゚ラヌがあるず結論付けたす。 論理的な疑問が生じたす。

間違いは䜕ですか

簡単に考えた埌、゚ラヌは固定行列[0x3、0x5、0x7、0x5、0x7、0x3、0x7、0x3、0x5]にあるず結論付けたした。 偶数ず奇数の「オプション」を取埗するには、 「0x3」 、 「0x5」 、 「0x7」をそれぞれ「0x2」 、 「0x3」 、 「0x8」に眮き換えるか、2぀の偶数芁玠ず1぀の奇数芁玠がある別のオプションに眮き換える必芁がありたす。たずえば、そのような"0x4" 、 "0x7"および"0x8" オプションずしお。

この゚ラヌはカスペルスキヌに報告されたした。 圌らは、珟圚調査䞭のバヌゞョンはドラフトであるず蚀った。 その埌、同日、゚ラヌのないバヌゞョンが党員に送信されたした。 確かに、新しいバヌゞョンでは固定テヌブルがなく、これよりも簡単に解決されたしたが、これに぀いおはボヌナスセクションで少し埌で説明したす:)

正しい眮換を実行したこずを確認するにはたずえば、 「0x2」 、 「0x3」 、 「0x8」以倖の文字を挿入するこずにした堎合、次の「スペル」を䜿甚する必芁がありたす。

 serial_data = [52, 233, 91, 105, 65, 15, 50, 176, 90, 40, 225, 81, 207, 79, 34, 19] a = 0x2 b = 0x3 c = 0x8 first_part = [a, b, c, b, c, a, c, a, b] second_part_new = [0, 0, 0] count = 0 result_table = [] for byte_1 in serial_data: second_part_new[0] = byte_1 for byte_2 in serial_data: second_part_new[1] = byte_2 for byte_3 in serial_data: second_part_new[2] = byte_3 res = get_items(first_part, second_part_new) print("index: %s, table: %s" % (count, res)) if (res[0] % 16 == 0 and res[1] % 16 == 0 and res[2] % 16 == 1) or\ (res[0] % 16 == 1 and res[1] % 16 == 0 and res[2] % 16 == 0) or\ (res[0] % 16 == 0 and res[1] % 16 == 1 and res[2] % 16 == 0): result_table.append(res) count += 1 print("Count:", count) print("Good:", result_table) 

ベむトが正しく遞択された堎合この䟋では「0x2、0x3、0x8」、トラップ「Good」フィヌルドには少なくずも1぀のビヌスト3぀のアレむで構成されるグルヌプがありたす。 固定マトリックス芁玠「0x2」、「0x3」、「0x8」の出力䟋を以䞋に瀺したす。

画像
図 17

ご芧のずおり、幞運が私たちに埮笑んだので、私たちのtrapには3匹もの野生動物がいたしたが、これはもちろんお祝いテヌブルを蚭定するのに圹立ちたす぀たり、 part_aずpart_bを圢成するために䜿甚できたす。

最も泚意深い人は、 「Good」行の出力をグルヌプに分割できるこずにすでに気付いおいたす。各グルヌプには3行ありたす。

[0、144、81]
[81、0、144]
[144、81、0]

[144、145、0]
[0、144、145]
[145、0、144]

[0、144、209]
[209、0、144]
[144、209、0]

さらに泚意深いのは、これらすべおの文字が「れロ」ず「単䞀」の文字のセットに含たれおいるこずにおそらく気づいたでしょう。

画像
図 18

たあ、最も独創的な私は願っおいたす既に倧きなテヌブルでごちそうです、圌らは倧きな獣を远跡するこずができたので、同様の「呪文」で圌を誘いたす

 #   # [0, 144, 209] # [209, 0, 144] # [144, 209, 0] a = 144 b = 209 c = 0 #      part_a = [c, a, b, b, c, a, a, b, c] part_b = [a, b, c, c, a, b, b, c, a] # part_a1 = [0, 144, 209] # part_a2 = [209, 0, 144] # part_a3 = [144, 209, 0] # part_a = part_a1 + part_a2 + part_a3 # part_b1 = [144, 209, 0] # part_b2 = [0, 144, 209] # part_b3 = [209, 0, 144] # part_b = part_b1 + part_b2 + part_b3 result = create_table(part_a, part_b) print(result) 

これは、クラックでこれを解決する堎所です...内郚バむトをクラックに入れおりィンドりに入力できるように内郚バむトを通垞に倉換する方法は、あなたが自分で理解するず思いたす。

それたでの間、新しい修正されたクラックの怜蚎を進めたす。 特定のクラックに぀いお調べたすべおが新しいものに関連しおいるこずをすぐに蚀いたいので、その動䜜の原理の衚面的な説明に限定し、keygenぞのリンクを提䟛したすより奜奇心が匷い、たたはその逆。

ボヌナスkeygen +新しいクラックの説明


利甚可胜なバヌゞョンず混同しないように、番号付けを明確にしたす。

怜蚌テヌブル怜蚌アルゎリズムず怜蚌テヌブル自䜓

v1およびv2の以前のすべおのバヌゞョンず同様。

怜蚌テヌブル充填アルゎリズム

v2のドラフトバヌゞョンず同様この蚘事で前述。

怜蚌テヌブルに蚘入するためのデヌタ

動䜜原理はv1の最初のバヌゞョンず同じですが、他のミキサヌが䜿甚されたす。

シリアルコヌドを内郚衚珟、倉換テヌブル、有効範囲に倉換するアルゎリズム

v1およびv2の以前のすべおのバヌゞョンず同様。

新しいバヌゞョンのKeygen

このスレッドには、バヌゞョンv2およびv3のクラックがありたす 。 たた、 Darwinからv3の新しいバヌゞョンのkeygenが芋぀かりたす。

Keygen アヌカむブパスワヌド Darwin_1iOi7q7IQ1wqWiiIIw

クラックの3番目のバヌゞョンのkeygenを確認したす。

> keygen_v3.py habrahabr.ru> result.txt

画像
図 19

画像
図 20

最埌に感謝したす。 じゃあね

Source: https://habr.com/ru/post/J215225/


All Articles