2013 Codegate Prequel binary 100
.NET 바이너리가 주어졌다.
이 바이너리 소스인데 좀 길지만 보면 쉽다.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Crack_Test.Properties;
namespace Crack_Test
{
// Token: 0x02000003 RID: 3
public class Crack_Game : Form
{
// Token: 0x06000004 RID: 4 RVA: 0x00002158 File Offset: 0x00000358
public Crack_Game()
{
this.a();
this.r.MaxLength = 25;
}
// Token: 0x06000005 RID: 5 RVA: 0x000021DC File Offset: 0x000003DC
public bool TextInput(int txt)
{
bool result;
if (this.r.MaxLength > this.r.TextLength)
{
TextBox textBox = this.r;
textBox.Text += txt;
result = true;
}
else
{
MessageBox.Show("length error!!");
result = false;
}
return result;
}
// Token: 0x06000006 RID: 6 RVA: 0x0000223C File Offset: 0x0000043C
private void m(object A_0, EventArgs A_1)
{
this.b = 1;
this.TextInput(this.b);
}
// Token: 0x06000007 RID: 7 RVA: 0x00002253 File Offset: 0x00000453
private void l(object A_0, EventArgs A_1)
{
this.b = 2;
this.TextInput(this.b);
}
// Token: 0x06000008 RID: 8 RVA: 0x0000226A File Offset: 0x0000046A
private void k(object A_0, EventArgs A_1)
{
this.b = 3;
this.TextInput(this.b);
}
// Token: 0x06000009 RID: 9 RVA: 0x00002281 File Offset: 0x00000481
private void j(object A_0, EventArgs A_1)
{
this.b = 4;
this.TextInput(this.b);
}
// Token: 0x0600000A RID: 10 RVA: 0x00002298 File Offset: 0x00000498
private void i(object A_0, EventArgs A_1)
{
this.b = 5;
this.TextInput(this.b);
}
// Token: 0x0600000B RID: 11 RVA: 0x000022AF File Offset: 0x000004AF
private void h(object A_0, EventArgs A_1)
{
this.b = 6;
this.TextInput(this.b);
}
// Token: 0x0600000C RID: 12 RVA: 0x000022C6 File Offset: 0x000004C6
private void g(object A_0, EventArgs A_1)
{
this.b = 7;
this.TextInput(this.b);
}
// Token: 0x0600000D RID: 13 RVA: 0x000022DD File Offset: 0x000004DD
private void f(object A_0, EventArgs A_1)
{
this.b = 8;
this.TextInput(this.b);
}
// Token: 0x0600000E RID: 14 RVA: 0x000022F4 File Offset: 0x000004F4
private void e(object A_0, EventArgs A_1)
{
this.b = 9;
this.TextInput(this.b);
}
// Token: 0x0600000F RID: 15 RVA: 0x0000230C File Offset: 0x0000050C
private void d(object A_0, EventArgs A_1)
{
this.b = 0;
this.TextInput(this.b);
}
// Token: 0x06000010 RID: 16 RVA: 0x00002324 File Offset: 0x00000524
private void c(object A_0, EventArgs A_1)
{
try
{
this.r.Text = string.Empty;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
// Token: 0x06000011 RID: 17 RVA: 0x0000236C File Offset: 0x0000056C
private void b(object A_0, EventArgs A_1)
{
this.Shadowkey = "N0\u0005\u001aO+/\fN<37JRLJ\u001e\f\u0014\u000f\u000f";
string data = string.Empty;
string str = string.Empty;
if (this.r.Text != "")
{
this.Shadowkey += "\u0014\u000f\u000f\u0017\u001c<J\a\u001a)%M\f\u0015\u001f<2\u000fE\u001e\u00122\u0010V9\u00166H-\u0012@";
data = AESCrypt.Encrypt(this.r.Text, Crack_Game.KeyValue);
str = this.xorToString(data);
Trace.WriteLine("Encrypt key:" + str);
this.TransFormable(this.r.Text);
if (this.r.Text.Length != 16)
{
string data2 = this.a.TransForm_S();
string text = this.a.TransForm_B(data2);
MessageBox.Show(text);
}
}
else
{
string text2 = this.a.Md5hash(this.r.Text);
byte[] array = this.a.stringTobyte(AESCrypt.Encrypt(this.r.Text, Crack_Game.KeyValue));
string str2 = "";
for (int i = 0; i < array.Length; i++)
{
str2 += string.Format(" {0:X2}", array[i]);
}
for (int i = 0; i < array.Length; i++)
{
array[i] ^= 67;
}
string data3 = this.a.ByteTostring_t(array);
byte[] array2 = this.a.stringTobyte(this.a.TransForm());
for (int i = 0; i < array2.Length; i++)
{
array2[i] ^= 67;
}
string text3 = AESCrypt.Decrypt(this.a.ByteTostring_t(array2), Crack_Game.KeyValue);
this.a.TransForm_B(data3);
Trace.WriteLine(this.a.TransForm_B(data3));
MessageBox.Show("input password :");
}
}
// Token: 0x06000012 RID: 18 RVA: 0x0000258C File Offset: 0x0000078C
public byte[] stringTobyte(string str)
{
return Encoding.UTF8.GetBytes(str.ToCharArray());
}
// Token: 0x06000013 RID: 19 RVA: 0x000025B0 File Offset: 0x000007B0
public string ByteTostring(byte[] bt)
{
string text = "";
for (int i = 0; i < bt.Length; i++)
{
text += Encoding.Default.GetString(bt, i, 1);
}
return text;
}
// Token: 0x06000014 RID: 20 RVA: 0x000025F4 File Offset: 0x000007F4
public void TransFormable(string Data)
{
if (Data.Length == 16)
{
if (this.xorToString(AESCrypt.Encrypt(this.r.Text, Crack_Game.KeyValue)) == this.lowkey)
{
string textToDecrypt = this.StringToXOR(this.a.ByteTostring_t(this.c));
string text = AESCrypt.Decrypt(textToDecrypt, Crack_Game.KeyValue);
MessageBox.Show(text);
}
else
{
string textToDecrypt2 = this.StringToXOR(this.a.ByteTostring_t(this.d));
string str = AESCrypt.Decrypt(textToDecrypt2, Crack_Game.KeyValue);
MessageBox.Show("Do you know ? " + str);
}
}
}
// Token: 0x06000015 RID: 21 RVA: 0x000026B0 File Offset: 0x000008B0
public string StringToXOR(string data)
{
string empty = string.Empty;
byte[] array = new byte[data.Length];
array = this.stringTobyte(data);
for (int i = 0; i < array.Length; i++)
{
array[i] ^= 37;
array[i] ^= 88;
}
return this.ByteTostring(array);
}
// Token: 0x06000016 RID: 22 RVA: 0x00002710 File Offset: 0x00000910
public string xorToString(string data)
{
string empty = string.Empty;
byte[] array = new byte[data.Length];
array = this.stringTobyte(data);
for (int i = 0; i < array.Length; i++)
{
array[i] ^= 21;
}
return this.ByteTostring(array);
}
// Token: 0x06000017 RID: 23 RVA: 0x00002765 File Offset: 0x00000965
private void a(object A_0, EventArgs A_1)
{
}
// Token: 0x06000018 RID: 24 RVA: 0x00002768 File Offset: 0x00000968
protected override void Dispose(bool disposing)
{
if (disposing && this.e != null)
{
this.e.Dispose();
}
base.Dispose(disposing);
}
// Token: 0x06000019 RID: 25 RVA: 0x000027A0 File Offset: 0x000009A0
private void a()
{
this.f = new Button();
this.g = new Button();
this.h = new Button();
this.i = new Button();
this.j = new Button();
this.k = new Button();
this.l = new Button();
this.m = new Button();
this.n = new Button();
this.o = new Button();
this.p = new Button();
this.q = new Button();
this.r = new TextBox();
this.s = new Label();
base.SuspendLayout();
this.f.Image = Resources.num_14;
this.f.Location = new Point(25, 62);
this.f.Name = "button1";
this.f.Size = new Size(56, 56);
this.f.TabIndex = 0;
this.f.UseVisualStyleBackColor = true;
this.f.Click += this.m;
this.g.Image = Resources.num_21;
this.g.Location = new Point(101, 62);
this.g.Name = "button2";
this.g.Size = new Size(56, 56);
this.g.TabIndex = 1;
this.g.UseVisualStyleBackColor = true;
this.g.Click += this.l;
this.h.Image = Resources.num_3;
this.h.Location = new Point(177, 62);
this.h.Name = "button3";
this.h.Size = new Size(56, 56);
this.h.TabIndex = 2;
this.h.UseVisualStyleBackColor = true;
this.h.Click += this.k;
this.i.Image = Resources.num_4;
this.i.Location = new Point(25, 124);
this.i.Name = "button4";
this.i.Size = new Size(56, 56);
this.i.TabIndex = 3;
this.i.UseVisualStyleBackColor = true;
this.i.Click += this.j;
this.j.Image = Resources.num_5;
this.j.Location = new Point(101, 124);
this.j.Name = "button5";
this.j.Size = new Size(56, 56);
this.j.TabIndex = 4;
this.j.UseVisualStyleBackColor = true;
this.j.Click += this.i;
this.k.Image = Resources.num_6;
this.k.Location = new Point(177, 124);
this.k.Name = "button6";
this.k.Size = new Size(56, 56);
this.k.TabIndex = 5;
this.k.UseVisualStyleBackColor = true;
this.k.Click += this.h;
this.l.Image = Resources.num_7;
this.l.Location = new Point(25, 188);
this.l.Name = "button7";
this.l.Size = new Size(56, 56);
this.l.TabIndex = 6;
this.l.UseVisualStyleBackColor = true;
this.l.Click += this.g;
this.m.Image = Resources.num_8;
this.m.Location = new Point(101, 188);
this.m.Name = "button8";
this.m.Size = new Size(56, 56);
this.m.TabIndex = 7;
this.m.UseVisualStyleBackColor = true;
this.m.Click += this.f;
this.n.Image = Resources.num_9;
this.n.Location = new Point(177, 188);
this.n.Name = "button9";
this.n.Size = new Size(56, 56);
this.n.TabIndex = 8;
this.n.UseVisualStyleBackColor = true;
this.n.Click += this.e;
this.o.Image = Resources.num_0;
this.o.Location = new Point(101, 249);
this.o.Name = "button10";
this.o.Size = new Size(56, 56);
this.o.TabIndex = 9;
this.o.UseVisualStyleBackColor = true;
this.o.Click += this.d;
this.p.Font = new Font("굴림", 17f);
this.p.Image = Resources.key_;
this.p.Location = new Point(25, 249);
this.p.Name = "button11";
this.p.Size = new Size(56, 56);
this.p.TabIndex = 10;
this.p.UseVisualStyleBackColor = true;
this.p.Click += this.b;
this.q.Image = Resources.key__;
this.q.Location = new Point(177, 249);
this.q.Name = "Bt_Delete";
this.q.Size = new Size(56, 56);
this.q.TabIndex = 11;
this.q.UseVisualStyleBackColor = true;
this.q.Click += this.c;
this.r.Enabled = false;
this.r.Location = new Point(25, 25);
this.r.MaxLength = 1;
this.r.Name = "textBox_Input";
this.r.Size = new Size(208, 21);
this.r.TabIndex = 12;
this.r.TextAlign = HorizontalAlignment.Right;
this.s.AutoSize = true;
this.s.Location = new Point(81, 370);
this.s.Name = "label_Msg";
this.s.Size = new Size(0, 12);
this.s.TabIndex = 13;
base.AutoScaleDimensions = new SizeF(7f, 12f);
base.AutoScaleMode = AutoScaleMode.Font;
this.BackgroundImage = Resources.codegate_back4;
base.ClientSize = new Size(263, 399);
base.Controls.Add(this.s);
base.Controls.Add(this.r);
base.Controls.Add(this.q);
base.Controls.Add(this.p);
base.Controls.Add(this.o);
base.Controls.Add(this.n);
base.Controls.Add(this.m);
base.Controls.Add(this.l);
base.Controls.Add(this.k);
base.Controls.Add(this.j);
base.Controls.Add(this.i);
base.Controls.Add(this.h);
base.Controls.Add(this.g);
base.Controls.Add(this.f);
this.Cursor = Cursors.Arrow;
this.Font = new Font("굴림", 9f);
base.FormBorderStyle = FormBorderStyle.FixedToolWindow;
base.Name = "Crack_Game";
base.StartPosition = FormStartPosition.CenterScreen;
this.Text = "Door_Lock";
base.TopMost = true;
base.Load += this.a;
base.ResumeLayout(false);
base.PerformLayout();
}
// Token: 0x04000003 RID: 3
private StringCrypt a = new StringCrypt();
// Token: 0x04000004 RID: 4
public static string KeyValue = "9e2ea73295c7201c5ccd044477228527";
// Token: 0x04000005 RID: 5
public string lowkey = "@DT$:~zRbD_!qFWQMAtC's[_t:&&YF\u007fWQE ^o-EBAr%(";
// Token: 0x04000006 RID: 6
private int b;
// Token: 0x04000007 RID: 7
private byte[] c = new byte[]
{63,30,57,47,20,78,50,54,51,5,37,41,82,40,69,30,42,56,36,73,60,68,79,86,24,73,76,19,9,27,42,4,82,42,28,86,79,11,17,63,23,14,48,64};
// Token: 0x04000008 RID: 8
private byte[] d = new byte[]
{
22,52,4,72,40,18,41,22,23,45,21,28,42,63,23,49,75,76,39,5,9,13,8,43,37,59,42,45,5,48,10,47,7,42,12,41,20,79,37,46,39,3126,64};
// Token: 0x04000009 RID: 9
public string Shadowkey = string.Empty;
// Token: 0x0400000A RID: 10
private IContainer e = null;
// Token: 0x0400000B RID: 11
private Button f;
// Token: 0x0400000C RID: 12
private Button g;
// Token: 0x0400000D RID: 13
private Button h;
// Token: 0x0400000E RID: 14
private Button i;
// Token: 0x0400000F RID: 15
private Button j;
// Token: 0x04000010 RID: 16
private Button k;
// Token: 0x04000011 RID: 17
private Button l;
// Token: 0x04000012 RID: 18
private Button m;
// Token: 0x04000013 RID: 19
private Button n;
// Token: 0x04000014 RID: 20
private Button o;
// Token: 0x04000015 RID: 21
private Button p;
// Token: 0x04000016 RID: 22
private Button q;
// Token: 0x04000017 RID: 23
private TextBox r;
// Token: 0x04000018 RID: 24
private Label s;
}
}
핵심 코드만 보자면 입력 받는 값의 길이는 16글자이다.
public void TransFormable(string Data)
{
if (Data.Length == 16)
{
if (this.xorToString(AESCrypt.Encrypt(this.r.Text, Crack_Game.KeyValue)) == this.lowkey)
{
string textToDecrypt = this.StringToXOR(this.a.ByteTostring_t(this.c));
string text = AESCrypt.Decrypt(textToDecrypt, Crack_Game.KeyValue);
MessageBox.Show(text);
}
else
{
string textToDecrypt2 = this.StringToXOR(this.a.ByteTostring_t(this.d));
string str = AESCrypt.Decrypt(textToDecrypt2, Crack_Game.KeyValue);
MessageBox.Show("Do you know ? " + str);
}
}
}
public string StringToXOR(string data)
{
string empty = string.Empty;
byte[] array = new byte[data.Length];
array = this.stringTobyte(data);
for (int i = 0; i < array.Length; i++)
{
array[i] ^= 37;
array[i] ^= 88;
}
return this.ByteTostring(array);
}
public static string KeyValue = "9e2ea73295c7201c5ccd044477228527";
public string lowkey = "@DT$:~zRbD_!qFWQMAtC's[_t:&&YF\u007fWQE ^o-EBAr%(";
private byte[] c = new byte[]{ 63,30,57,47,20,78,50,54,51,5,37,41,82,40,69,30,42,56,36,73,60,68,79,86,24,73,76,19,9,27,42,4,82,42,28,86,79,11,17,63,23,14,48,64};
private byte[] d = new byte[]{
22,52,4,72,40,18,41,22,23,45,21,28,42,63,23,49,75,76,39,5,9,13,8,43,37,59,42,45,5,48,10,47,7,42,12,41,20,79,37,46,39,31,26,64};
우선 16글자만 맞추고 입력하면 아래와 같은 글자를 출력해준다. 그러므로 우리는 lowkey랑 입력받은 걸 AES Encrypt하고 xor한 값이 같으면 c 를 XOR연산 후에 AES Decrypt 해준다. 길이만 맞고 lowkey랑은 다르면 d를 Decrypt 해준다. 우리는 이를 이용해서 풀 수 있다.
만약 c와 d를 바꾸고 길이만 16으로 맞춘 후 아무거나 입력한다면 플래그가 담인 것을 Decrypt하게 된다. 우선은 푸는 방법은 여러개가 있다. 바이너리를 패치해서 c와 d를 바꾸거나 이 .cs 파일을 변수를 서로 바꿔주고 컴파일 하면 된다.
나는 바이너리 패치를 했다. 그냥 d를 c로 바꿔서 c가 Decrypt 되게 했다.
이제 이 바이너리를 길이만 맞추고 실행해주면 c가 Decrypt 되서 MessageBox로 출력된다.
다른 방법으로는 c의 테이블 값을 가져오고 역연산 해주면 된다.
# -*- coding:utf-8 -*-
import base64
# length = 16
c=[63,30,57,47,20,78,50,54,51,5,37,41,82,40,69,30,42,56,36,73,60,68,79,86,24,73,76,19,9,27,42,4,82,42,28,86,79,11,17,63,23,14,48,64]
enc = []
for i in c:
enc.append(i^37^88)
a = ''.join(chr(i) for i in enc)
a = base64.b64decode(a)
print a
우선은 StringToXOR의 값을 먼저 구해주었다. BcDRi3OKNxXT/U8cWEY4A92+e41ntfWy/Wa+2vlBjsM=
AES-256-CBC Decrypt 하는 것을 찾다가 php의 crypt_decrypt를 이용해서 풀었다.
<?php
$text = "BcDRi3OKNxXT/U8cWEY4A92+e41ntfWy/Wa+2vlBjsM=";
$algorithm = MCRYPT_RIJNDAEL_256;
$mode = MCRYPT_MODE_CBC;
$keyvalue = '9e2ea73295c7201c5ccd044477228527';
$bytes = $keyvalue;
$iv = $key = $bytes;
$flag = mcrypt_decrypt($algorithm, $key, base64_decode($text),$mode, $iv);
print $flag;
?>
그냥 C# 변수 서로 바꿔주고 몇개 바꾸고 컴파일 해주면 된다. 그러면 passcode는 198711102130301
이렇게 나온다.
FLAG : code9ate2013 Start