CodeEngn basic 17(write up)
안녕하세요. 오랜만 입니다. 요즘 이것 저것 준비하면서 바쁘게 지내서 포스팅을 많이 못했네요.. 최근에 CodeEngn문제 다시 풀어보고 있는데 리버싱을 처음접하는 사람이 조금 hard하다라는 문제 위주로 포스팅 진행하고 있습니다.
이 문제를 보면 KEY값 주어지고 NAME이 한자리이라고 하네요.. 그리고 NAME값의 MD5 해쉬값을 구하라고 하네요..
음 처음 봤을 때 A-Z,a-z,0~9이런식으로 무작위 대입하면 답이 나올꺼라고 생각하고 답을 구했는데 이 방법은 리버싱 실력향상에 도움이 되지 못합니다. 따라서 내부적인 코드를 분석해보겠습니다.
KEY값은 BEDA-2F56-BC4F4368-8A71-870B입니다.
올리 디버거를 이용해 내부 STRING을 서치 합니다.
다음 코드에서 0045BB24에 CMP구문이 보이는데 디버깅 결과 EAX에 제가 입력한 NAME이 들어갑니다. 근데 문제에서 NAME은 한 자리라 했으니까 3을 1로 EDIT해서 패치해줘야 합니다. 패치 과정은 다 아실 거라고 생각하고 패스하겠습니다.
CMP EAX,3 -> CMP EAX,1로 바꿔주세요.
바꾼 부분을 다시 디버깅하면 마지막 성공분기로 갈때 CALL 046B850에서 NAME을 이용해서 KEY값을 생성합니다. 이부분을 스텝 인투(F7)하겠습니다.
이제 이 이부분을 볼수 있는데 여기서 ESI레지스터 입력값이 들어있고 이것을 통해 연산합니다.
이 과정을 통해 BEDA-2F56-BC4F4368-8A71-870B 중 BEDA값을 생성합니다. 그러면 BEDA값하고 포함되는
코드를 작성하면 됩니다.
정리하면
ESI(입력값)+=EDX
ESI = ESI * 0x772
EDX = ESI
EDX = EDX * ESI
ESI = ESI +EDX
ESI = ESI | ESI
ESI = ESI * 0x474
ESI = ESI + ESI
EDX = ESI
이렇게 됩니다. 이것을 이용해서 C#으로 코드를 작성해보겠습니다.
먼저 ASCII코드를 이용해서 A-Z, a-z까지의 문자를 불러오고 배열에 저장합니다. 그리고 연산을 통해 key값이 포함되는 배열의 i번째를 출력해 NAME을 알아냅니다.
using System;
namespace basic17
{
class Program
{
static void Main(string[] args)
{
char[] array = new char[52];
ulong[] hexarray = new ulong[52];
string key = "BEDA";
ulong d;
int c = 65;
for(int i=0; i<26; i++)
{
array[i] = (char)c;
c++;
}
c += 6;
for(int i=26; i<52; i++)
{
array[i] = (char)c;
c++;
}
for(int i=0; i<52; i++)
{
hexarray[i] = (ulong)array[i];
hexarray[i] *= 0x772;
d = hexarray[i];
hexarray[i] = d*hexarray[i];
hexarray[i] = hexarray[i] + d;
hexarray[i] |= hexarray[i];
hexarray[i] *= 0x474;
hexarray[i] += hexarray[i];
Console.WriteLine("{0} : {1}",array[i],hexarray[i].ToString("X")); //x X대 소문자
if (hexarray[i].ToString("X").Contains(key))
Console.WriteLine("name = {0}", array[i]);
}
}
}
}
이제 name이 F라는 것을 아실 수 있습니다.
이것의 md5 hash값은 800618943025315F869E4E1F09471012입니다.
이상 읽어주셔서 감사합니다.