1. 문제
Name이 CodeEngn일때 Serial은 28BF522F-A5BE61D1-XXXXXXXX 이다. XXXXXXXX 를 구하시오
키젠 !
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); } } } } }
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; } } }
결국 마지막 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; } } }
참 더러운 문제네 ;;;;
결국 0부터 증가시키면서 브포 때리면 num4=299913681 인 경우 서
4. 몰랐던 개념
결론. 하루종일 삽질했으나 얻은건 없고 ㄷㄷ 걍 단순히 한 6시간 돌려놓으면 됐을 듯
'워게임 > CodeEngn' 카테고리의 다른 글
[CodeEngn] Advance RCE L09 (0) | 2021.02.04 |
---|---|
[CodeEngn] Advance RCE L08 (0) | 2021.02.02 |
[CodeEngn] Advance RCE L06 (0) | 2021.01.30 |
[CodeEngn] Advance RCE L05 (0) | 2021.01.29 |
[CodeEngine] Advance RCE L04 (0) | 2021.01.28 |
Uploaded by Notion2Tistory v1.1.0