본문 바로가기

Technical Docs/Reversing

Crackmes.one - 4

오늘도 2.0 짜리 문제를 풀어봅시다.

 

 

문제를 열면 매번 비슷합니다. 키, 패스워드 등을 입력하라고 하고 내가 입력한 값이 맞으면 Correct, 틀리면 Wrong를 뱉는 방식이죵...

 

 

그러면은 IDA를 열어서 해당 문자열을 검색해봅시다. 바로 검색이됩니다!

if(v!19)에서 걸리고, v19는 sub_140001290 요 함수를 호출합니다.
그러면 우리는 눈치 9단이니까 대충 내 문자열을 정답과 처리하는곳이 sub_140001290 여기인거같군요.

 

그전에 위에서부터 한번 메인함수를 쭉 읽어봅시다. 근데 이부분은 저도 때려맞춘거라 왜 저부분이 문자열 길이인지 모르겠다능... v11이 문자열길이인데 그걸 벗어나면 invalid 쪽으로 넘어가더라구용... 그래서 대충 아 문자열 10자리구나.. 라고 생각합니다.

 

그러면 대망의 sub_140001290 함수로 들어가 봅시다. 중요한게 if(!v19) 이기 때문에 해당 함수는 return을 0으로 떨어져야 정답으로 갈 수 있습니다. 그래서 우리한테 중요한건 여기죠!
if( *((char *)v6 + *(int *)v5 != *v4 - 5 )

이부분 입니다. 이거만 잘 넘기면 goto LABEL_13; 이 리턴시키는 부분이기 때문에 이쪽으로 들어가지 않습니다.

 

참고로 v6는 우리가 입력한 입력값

v5는 아래와 같고 (아래 v5 = v12 있음)

 

v4는 아래와 같습니다. (아래 v4=v2 있음)

 

그러면 *((char *)v6 + *(int *)v5 요 부분부터 확인해볼껀데 왜냐면 뒤에는 쉬우니까...

*((char *)v6 이거는 우리가 입력한 문자열의 첫번째 주소를 가르킵니다. 그리고 + 뒤에 값은 이전에도 봤듯이 문자열의 index값으라고 생각하면 편합니다.

 

그러면 input[ *(int *)v5 ] 의 모양세가 되는건데 우선 v12의 값을 보여드리겠습니다. v12의 int 128 (16바이트는 아래와 같습니다.)

 

하지만 위에 v12 배열 선언부분을 보면 00,20,30,10,40 으로 가져오고있습니다.

 

그리고 중요한부분인 if 문안에서는 int *로 가져오고 있습니다. (4바이트씩)

그러니까 우리가 점진적으로 가져가는 값은 다음과 같습니다. (메모리에는 저렇게 올라가지만 실제로 읽을때는 00 00 00 07 이라서 7입니다.)

 

v12[0]
v12[1]
v12[2]
v12[3]
v12[4]

 

여기서 중요한건 이부분이 v5에 넣는 부분이고,

 

실제 비교하는곳의 어셈블리를 보면 이런식으로 가져옵니다. 그러니까 input(v5) 가 아니고 input(*v5) 라고 생각해야합니다. v5에 값을 그냥 더하는겜 아니라 v5에서 4바이트 자른 값을 인덱스로 더해줘야 합니다.

 

뒤에 *v4 - 5 부분은 간단합니다. 그냥 v4 값 가져와서 5를 빼주면됩니다 ^^;;

 

그러면 해당 부분을 파이썬 코드로짜면 다음과 같습니다.

a는 그냥 임의의 값이라고 생각하면됩니다.

 

해당 프로그램을 실행시키면 짜잔 답이나옵니다.

 

그리고 정답을 넣어주면 아래같이 짜잔!

 

사실 이걸로 하는것보다 동적으로 디버깅하는게 정답은 더 빠르게 얻을 수 있지만... 그래도 정적으로 분석하는 부분 연습할겸 이렇게 올립니다!

'Technical Docs > Reversing' 카테고리의 다른 글

crackemes.one - 5  (0) 2024.08.05
Crackmes.one - 3  (4) 2024.07.22
Crackemes.one - 2  (0) 2024.07.19
Crackmes.one - 1  (0) 2024.07.17