-
还是想刷一些题,在此简单记录一下
-
.net逆向,用dnspy打开
-
private static void Main(string[] args) { ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true"); FileStream fileStream = File.OpenRead("gamemessage"); int num = (int)fileStream.Length; Program.memory = new byte[num]; fileStream.Position = 0L; fileStream.Read(Program.memory, 0, num); Console.Title = "♠ Blackjack Game" + new string(' ', 11) + "...Based on Konstantin Tarkus' code"; Console.BufferWidth = (Console.WindowWidth = 70); Console.BufferHeight = (Console.WindowHeight = 26); Console.CursorVisible = false; ArrayList arrayList = new ArrayList(); Game game = new Game(); game.Player.BalanceChanged += Program.OnBalanceChanged; game.LastStateChanged += Program.OnLastStateChanged; game.AllowedActionsChanged += Program.OnAllowedActionsChanged; game.Dealer.Hand.Changed += Program.OnHandChanged; game.Player.Hand.Changed += Program.OnHandChanged; game.Play(20m, 5m); for (;;) { ConsoleKey key = Console.ReadKey(true).Key; ConsoleKey consoleKey = key; if (consoleKey <= ConsoleKey.Add) { switch (consoleKey) { case ConsoleKey.Enter: { bool flag = (game.AllowedActions & GameAction.Deal) == GameAction.Deal; if (flag) { game.Deal(); } else { game.Stand(); } continue; } case (ConsoleKey)14: case (ConsoleKey)15: case (ConsoleKey)16: case (ConsoleKey)17: case (ConsoleKey)18: case ConsoleKey.Pause: case (ConsoleKey)20: case (ConsoleKey)21: case (ConsoleKey)22: case (ConsoleKey)23: case (ConsoleKey)24: case (ConsoleKey)25: case (ConsoleKey)26: case (ConsoleKey)28: case (ConsoleKey)29: case (ConsoleKey)30: case (ConsoleKey)31: case ConsoleKey.PageUp: case ConsoleKey.PageDown: case ConsoleKey.End: case ConsoleKey.Home: case ConsoleKey.LeftArrow: case ConsoleKey.RightArrow: case ConsoleKey.Select: case ConsoleKey.Print: case ConsoleKey.Execute: case ConsoleKey.PrintScreen: case ConsoleKey.Insert: case ConsoleKey.Delete: case ConsoleKey.Help: case (ConsoleKey)58: case (ConsoleKey)59: case (ConsoleKey)60: case (ConsoleKey)61: case (ConsoleKey)62: case (ConsoleKey)63: case (ConsoleKey)64: continue; case ConsoleKey.Escape: Program.verifyCode(arrayList, game); continue; case ConsoleKey.Spacebar: { bool flag2 = (game.AllowedActions & GameAction.Deal) == GameAction.Deal; if (flag2) { game.Deal(); } else { game.Hit(); } continue; } case ConsoleKey.UpArrow: break; case ConsoleKey.DownArrow: goto IL_5A0; case ConsoleKey.D0: arrayList.Add('0'); continue; case ConsoleKey.D1: arrayList.Add('1'); continue; case ConsoleKey.D2: arrayList.Add('2'); continue; case ConsoleKey.D3: arrayList.Add('3'); continue; case ConsoleKey.D4: arrayList.Add('4'); continue; case ConsoleKey.D5: arrayList.Add('5'); continue; case ConsoleKey.D6: arrayList.Add('6'); continue; case ConsoleKey.D7: arrayList.Add('7'); continue; case ConsoleKey.D8: arrayList.Add('8'); continue; case ConsoleKey.D9: arrayList.Add('9'); continue; case ConsoleKey.A: arrayList.Add('A'); continue; case ConsoleKey.B: arrayList.Add('B'); continue; case ConsoleKey.C: arrayList.Add('C'); continue; case ConsoleKey.D: arrayList.Add('D'); continue; case ConsoleKey.E: arrayList.Add('E'); continue; case ConsoleKey.F: arrayList.Add('F'); continue; case ConsoleKey.G: arrayList.Add('G'); continue; case ConsoleKey.H: arrayList.Add('H'); continue; case ConsoleKey.I: arrayList.Add('I'); continue; case ConsoleKey.J: arrayList.Add('J'); continue; case ConsoleKey.K: arrayList.Add('K'); continue; case ConsoleKey.L: arrayList.Add('L'); continue; case ConsoleKey.M: arrayList.Add('M'); continue; case ConsoleKey.N: arrayList.Add('N'); continue; case ConsoleKey.O: arrayList.Add('O'); continue; case ConsoleKey.P: arrayList.Add('P'); continue; case ConsoleKey.Q: arrayList.Add('Q'); continue; case ConsoleKey.R: arrayList.Add('R'); continue; case ConsoleKey.S: arrayList.Add('S'); continue; case ConsoleKey.T: arrayList.Add('T'); continue; case ConsoleKey.U: arrayList.Add('U'); continue; case ConsoleKey.V: arrayList.Add('V'); continue; case ConsoleKey.W: arrayList.Add('W'); continue; case ConsoleKey.X: arrayList.Add('X'); continue; case ConsoleKey.Y: arrayList.Add('Y'); continue; case ConsoleKey.Z: arrayList.Add('Z'); continue; default: if (consoleKey != ConsoleKey.Add) { continue; } break; } game.Player.Bet += 1m; } else { if (consoleKey == ConsoleKey.Subtract) { goto IL_5A0; } if (consoleKey == ConsoleKey.Oem1) { arrayList.Add(":"); } } continue; IL_5A0: game.Player.Bet -= 1m; } }
-
往内存里加载了个文件,先观察一下对这个文件如何加密的
-
找到如下函数:
-
private static void verifyCode(ArrayList arrayList, Game game) { string str = ""; for (int i = 0; i < arrayList.Count; i++) { str += arrayList[i].ToString()[0].ToString(); } Program.goldFunc(arrayList, game); arrayList.Clear(); }
-
跟进:private static void goldFunc(ArrayList input, Game game)
-
找到几处关键加密:
-
else { bool flag23 = Program.memcmp1(input, "MF3K", 4); if (flag23) { try { game.Player.Bet -= 22m; for (int i = 0; i < Program.memory.Length; i++) { byte[] array = Program.memory; int num = i; array[num] ^= 34; } Environment.SetEnvironmentVariable("AchivePoint1", game.Player.Balance.ToString()); } catch { } }
-
简单异或
-
else { bool flag41 = Program.memcmp1(input, "EEPW", 4); if (flag41) { try { game.Player.Balance += 175m; byte[] key = new byte[] { 66, 114, 97, 105, 110, 115, 116, 111, 114, 109, 105, 110, 103, 33, 33, 33 }; ICryptoTransform cryptoTransform = new RijndaelManaged { Key = key, Mode = CipherMode.ECB, Padding = PaddingMode.Zeros }.CreateDecryptor(); Program.m = cryptoTransform.TransformFinalBlock(Program.memory, 0, Program.memory.Length); Environment.SetEnvironmentVariable("AchivePoint2", game.Player.Balance.ToString()); } catch { } }
-
AES-ECB加密,有key可解密
-
将gamemessage文件拖进cyberchef进行解密,
-
找到MZ头,dump下来用dnspy分析
-
关键函数如下:
-
using System; using System.Linq; using System.Text; using System.Windows.Forms; namespace T1Class { // Token: 0x02000002 RID: 2 public class T1 { // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250 private static void Check1(ulong x, ulong y, ulong z, byte[] KeyStream) { int num = -1; for (int i = 0; i < 320; i++) { x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1UL) | x << 1); y = (((y >> 30 ^ y >> 27) & 1UL) | y << 1); z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1UL) | z << 1); bool flag = i % 8 == 0; if (flag) { num++; } KeyStream[num] = (byte)((long)((long)KeyStream[num] << 1) | (long)((ulong)((uint)((z >> 32 & 1UL & (x >> 30 & 1UL)) ^ (((z >> 32 & 1UL) ^ 1UL) & (y >> 31 & 1UL)))))); } } // Token: 0x06000002 RID: 2 RVA: 0x00002110 File Offset: 0x00000310 private static void ParseKey(ulong[] L, byte[] Key) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { Key[i * 4 + j] = (byte)(L[i] >> j * 8 & 255UL); } } } // Token: 0x06000003 RID: 3 RVA: 0x0000215C File Offset: 0x0000035C public T1() { try { string environmentVariable = Environment.GetEnvironmentVariable("AchivePoint1"); string environmentVariable2 = Environment.GetEnvironmentVariable("AchivePoint2"); string environmentVariable3 = Environment.GetEnvironmentVariable("AchivePoint3"); bool flag = environmentVariable == null || environmentVariable2 == null || environmentVariable3 == null; if (!flag) { ulong num = ulong.Parse(environmentVariable); ulong num2 = ulong.Parse(environmentVariable2); ulong num3 = ulong.Parse(environmentVariable3); ulong[] array = new ulong[3]; byte[] array2 = new byte[40]; byte[] array3 = new byte[40]; byte[] array4 = new byte[12]; byte[] first = new byte[] { 101, 5, 80, 213, 163, 26, 59, 38, 19, 6, 173, 189, 198, 166, 140, 183, 42, 247, 223, 24, 106, 20, 145, 37, 24, 7, 22, 191, 110, 179, 227, 5, 62, 9, 13, 17, 65, 22, 37, 5 }; byte[] array5 = new byte[] { 60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227 }; array[0] = num; array[1] = num2; array[2] = num3; T1.Check1(array[0], array[1], array[2], array2); bool flag2 = first.SequenceEqual(array2); if (flag2) { T1.ParseKey(array, array4); for (int i = 0; i < array5.Length; i++) { array5[i] ^= array4[i % array4.Length]; } MessageBox.Show("flag{" + Encoding.Default.GetString(array5) + "}", "Congratulations!", MessageBoxButtons.OK); } } } catch (Exception) { } } } }
-
逻辑很简单,我们首先用z3解一下array[0], array[1], array[2]这三个数据
-
如下照抄dnspy即可写出脚本:
-
from z3 import * x,y,z=BitVecs('x y z',64) s=Solver() KeyStream=[0]*40 array2 = [101, 5, 80, 213, 163, 26, 59, 38, 19, 6, 173, 189, 198, 166, 140, 183, 42, 247, 223, 24, 106,20, 145, 37, 24, 7, 22, 191, 110, 179, 227, 5, 62, 9, 13, 17, 65, 22, 37, 5] num=-1 for i in range(320): x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1) y = (((y >> 30 ^ y >> 27) & 1) | y << 1) z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1) if i%8==0: if i!=0: s.add(KeyStream[num]==array2[num]) num += 1 KeyStream[num] = (KeyStream[num] << 1) | (((z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1)))) print(s.check()) print(s.model()) [y = 868387187, x = 156324965, z = 3131229747]
-
接着照抄dnspy:
-
def ParseKey(array,key): for i in range(3): for j in range(4): key[i * 4 + j] = ((array[i] >> j * 8) & 255) return key array=[156324965,868387187,3131229747] array4=[0]*12 array4=ParseKey(array,array4) array5 = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227] c='' for i in range(len(array5)): c+=chr(array5[i]^array4[i%12]) print('flag{'+c+'}')
-
成功得到:flag{Y0u_@re_G3meM3s7er!}
-
该题主要考察文件加密,C#语言,以及算法“照抄”能力。。。
[强网杯 2022]GameMaster Writeup
发布于
2023-12-15
|
10分钟
|
1600字数
|
浏览量::
- 本文作者: Tanggerr
- 本文链接: https://Tanggerr.github.io/post/qiang-wang-bei-2022gamemaster-writeup/
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
0%
召唤看板娘
x
感谢您的支持,我会继续努力的!
扫码打赏,你说多少就多少