1. 문제
Name이 CodeEngn일때 Serial은 28BF522F-A5BE61D1-XXXXXXXX 이다.
XXXXXXXX 를 구하시오
Plain Text
복사
키젠 !
C# + .net 이니 dnspy로 분석하면 될듯
2. 접근방법
메인부터 차찬히 봐보자. 는 안됨. 사용된 함수이름을 기준으로 쫙 스캔을 한번 해보자. 어디서부터 보는게 좋을까..
보면 button1_click이랑 button2_click이 보인다. 아까 check 버튼이랑 close 버튼이 있는데 저건거 같음. 한번 확인해보자
여기가 맞는듯. 디버깅해본 결과 textBox1이 Name이고 textBox2가 시리얼이다. Name은 5이상 27이하의 사이즈를 가져야하며, 시리얼은 8바이트-8바이트-8바이트 형식으로 입력해야 한다.
' - ' 기준으로 숫자를 잘라서 num, num2, num3에 넣는다. 그다음 Name값을 qwerty() 저기다 인자로 넣고 나온 결과값을 num4에 넣는다.
•
num : 키 첫 8바이트
•
num2 : 키 그다음 8바이트
•
num3 : 키 다음 8바이트
•
num4 : Name을 괴상한 함수에 넣고 나온 결과값
그다음 Name의 해시를 계산해서 hashCode에 저장한뒤, num3과 xor연산을 한다
•
hashCode : Name의 해시값 → GetHashCode() 함수 이용
•
num3 = num3 ^ hashCode
그다음 yreee 배열에 num, num2, num, num2 순으로 저장한다
•
yreee[0] = num
•
yreee[1] = num2
•
yreee[2] = num
•
yreee[3] = num2
그다음 vxzzz함수에다가 yreee, ewrrr, 2415796773, num3을 인자로 넣고 호출한다.
vxzzz()이 실제 키젠하는 중요 로직이다. 물론 분석해서 역연산 로직 코드 짤라고 했으나 복잡해서 안함 ㅋ
vxzzz()의 호출이 끝나면 yreee배열의 값이 바뀐다. (내부에서 바뀌는 로직이 있음)
해당 함수 반환 값이 참이고, yreee[2]와 hashCode가 같고, yreee[3]이 num4와 동일하면 성공이다.
3. 풀이
문제에서 키의 16바이트 부분을 알려줬기 때문에 마지막 8바이트만 구하면 된다. 디버깅해본 결과, hashCode 값과 this.ewrrr 는 고정값이므로 디버깅시에 확인한 값을 그냥 고정으로 하여 harness 마냥 buttonclick 함수를 따로 뺏다
using System;
namespace advance_rev
{
using System;
class Program
{
static bool vxzzz(uint[] rwerqw, uint[] kgtsdfs, uint pgdsfa, uint fsfsdf)
{
pgdsfa ^= fsfsdf;
uint num = pgdsfa % 57 - 1;
uint num2 = rwerqw[0];
uint num3 = rwerqw[1];
uint num4 = num;
uint num5 = pgdsfa << (int)((byte)(97 ^ num + 68));
if (num == 0)
{
return false;
}
while (num-- > 0)
{
uint num6 = num4 / 16;
uint num7 = num2 << (int)((byte)(num4 / 8));
uint num8 = num2 >> (int)(3 + (byte)num6);
uint num9 = num4 / 4 + 3;
uint num10 = num9;
num9 = kgtsdfs[(int)((UIntPtr)((num5 >> (int)((byte)num9)) % 4))];
uint num11 = num5 + num9;
num3 -= ((num7 ^ num8) + num2 ^ num11) - num;
num5 -= pgdsfa;
num3 -= num;
num7 = num3 << (int)((byte)(num10 + 1) ^ 8);
num8 = num3 >> (int)((byte)(num4 / 2 - num10 + 23) ^ 25);
if (num == num4)
{
num3 ^= num;
}
if (num == num4 / 2 + (num10 ^ 27))
{
num10 = (num7 ^ num8) + (num3 ^ num);
}
else
{
num10 = (num7 ^ num8) + num3;
}
num2 -= (num10 ^ num5 + kgtsdfs[(int)((UIntPtr)(num5 & 3))]);
}
rwerqw[0] = (num2 ^ 4);
rwerqw[1] = (num3 ^ 7);
rwerqw[2] = (rwerqw[1] ^ (uint)((byte)((num4 + 1) / 3 - 4)));
rwerqw[3] = (rwerqw[0] ^ (uint)((byte)(num4 - 21 + 1 ^ 8)));
rwerqw[0] = (rwerqw[0] ^ kgtsdfs[4]);
rwerqw[1] = (rwerqw[1] ^ kgtsdfs[5]);
return true;
}
static void Main(string[] args)
{
String textBox1 = "CodeEngn";
uint num = 0x28BF522F;
uint num2 = 0xA5BE61D1;
uint aaa = 0xB4E4E0D5;
uint hashCode = 0x82AD30CB;
uint[] yreee = new uint[4];
uint[] errr = new uint[6];
errr[0] = 0x408112F1;
errr[1] = 0x1A3B0B51;
errr[2] = 0x2957C9FD;
errr[3] = 0x1B327D1D;
errr[4] = 0xA38D0AF1;
errr[5] = 0x2AD5E941;
uint num3;
uint num4;
for (num3 = 170126657; num3 < 4294967295; num3 += 1)
{
num4 = num3;
num4 ^= hashCode;
yreee[0] = num;
yreee[1] = num2;
yreee[2] = num;
yreee[3] = num2;
if (vxzzz(yreee, errr, 2415796773, num4))
{
if (yreee[2] == hashCode && yreee[3] == aaa)
{
Console.Write(Convert.ToString(num4, 16));
return;
}
Console.WriteLine(num4);
}
}
}
}
}
C#
복사
vscode에서 빌드해서 돌렸는데 안나옴 ㅋ.ㅋ.ㅋ.ㅋ.ㅋ.ㅋ.ㅋ..ㅋ.ㅋ.ㅋㅇ러니아럼ㄴㅇ;ㅣㅏ럼ㄴ이ㅏ러
뭐지? 뭐가 틀린거지
결국 롸업을 본 결과 GetHashCode() 요 놈이 포인트였다. 32bit랑 64bit랑 반환하는 값이 다르다. 문제는 32bit이기 때문에 현 내 시스템에선 안된다. 그렇기 때문에 앞에 알려준 16바이트 키도 64bit에선 저게 아니다.
A-B-C 키 형태에서 64bit에서 msgbox 출력시키려면 A,B,C 모두 브포를 때려야 한다. 따라서 빠르게
win7 32bit를 지인에게 얻고, vm을 새로 깔고,, 휴 개 고생해서 겨우 환경 맞추고 다시 시작
알고보니 dnspy에서 코드패치가 된다. 하... 그래서 앞에 쓰잘대기 없는 조건문 다 지우고 코드 패치 진행함
// WindowsFormsApplication2.Form1
// Token: 0x0600000A RID: 10 RVA: 0x000025BC File Offset: 0x000007BC
private void button1_Click(object sender, EventArgs e)
{
ytrewq ytrewq = new ytrewq();
uint num = 730887276U;//0x28BF522F
uint num2 = 2238254937U; //0xA5BE61D1
string text = "CodeEngn";
uint num3 = ytrewq.qwerty(Form1.dfgsf(text));
uint hashCode = (uint)text.GetHashCode();
for (uint num4 = 0U; num4 < 4294967295U; num4 += 1U)
{
uint num5 = num4;
num5 ^= hashCode;
this.yreee[0] = num;
this.yreee[1] = num2;
this.yreee[2] = num;
this.yreee[3] = num2;
if (this.vxzzz(this.yreee, this.ewrrr, 2415796773U, num5) && this.yreee[2] == hashCode && this.yreee[3] == num3)
{
MessageBox.Show("success!!", "Fine!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
return;
}
}
}
C#
복사
결국 마지막 8바이트만 브포 때리면 되는데 ... 저것도 안됌. ㅋㅋ;ㅋㄴ아ㅣ러ㅣㄴㅇ마럼니아러
뭐지? 아니 근데 라인별로 디버깅해보니까 안되는게 아니라 시간이 존오오오오오오오나 걸리는 거였음. 저기 vxzzz() 함수에서 시간이 오래걸림 ;; 내부에서 또 while로 존나 돔 ;;
걍 저 num4 초기값을 정답 근처로 두고 했음 ;
// WindowsFormsApplication2.Form1
// Token: 0x0600000A RID: 10 RVA: 0x000025BC File Offset: 0x000007BC
private void button1_Click(object sender, EventArgs e)
{
ytrewq ytrewq = new ytrewq();
uint num = 730887276U;//0x28BF522F
uint num2 = 2238254937U; //0xA5BE61D1
string text = "CodeEngn";
uint num3 = ytrewq.qwerty(Form1.dfgsf(text));
uint hashCode = (uint)text.GetHashCode();
for (uint num4 = 299913660U; num4 < 4294967295U; num4 += 1U)
{
uint num5 = num4;
num5 ^= hashCode;
this.yreee[0] = num;
this.yreee[1] = num2;
this.yreee[2] = num;
this.yreee[3] = num2;
if (this.vxzzz(this.yreee, this.ewrrr, 2415796773U, num5) && this.yreee[2] == hashCode && this.yreee[3] == num3)
{
MessageBox.Show("success!!", "Fine!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
return;
}
}
}
C#
복사
참 더러운 문제네 ;;;;
결국 0부터 증가시키면서 브포 때리면 num4=299913681 인 경우 성공한다. ㅅㅂ
4. 몰랐던 개념
결론. 하루종일 삽질했으나 얻은건 없고 ㄷㄷ 걍 단순히 한 6시간 돌려놓으면 됐을 듯