문제를 다운받고 ida로 열어보자
[main]
0x41 (61) 만큼 입력을 받고, check_key로 확인한다음 맞으면 flag파일을 열어서 출력해준다.
[cheak_key]
입력값이 10이상, 64이하 이면, 입력값을 encoding한다음 OO]oUU2U<sU2UsUsK 와 비교한다.
[encoding]
loc_40083C가 핵심인데, 먼저 encoding에 사용되는 변수들을 보기편하게 바꿔보자
- var_8 : 64d 만큼 할당한 문자배열 --> m[]
- var_C : 입력값의 길이 --> len
- var_10 : iterator --> i
- var_11 : 0x48 --> v
- 입력값 : s[]
- 0xEA0EA0EB : v2
저는 ida pro가없으니 이제부터 encoding루틴을 직접 handray해보겠습니다.
루틴은 4단계로 나눠서 설명해드릴께요
[ 반복문 ]
while ( i < len )
[ First ]
E1 = (s[i] + 0xC ) * v + 0x11
[ Second ]
E2 = ( (E1 * v2) >> 32 ) >> 6
E2 = E2 - (E1>>31)
[ Third ]
E2 = ( E1 - E2 * 0x46 ) + 0x30
[ Last ]
m[i]=E2
v=m[i]
i++
[ 최종루틴 ]
while (i<len) {
E1 = (s[i] + 0xC ) * v + 0x11
E2 = ( (E1 * v2) >> 32 ) >> 6
E2 = E2 - (E1>>31)
E2 = ( E1 - E2 * 0x46 ) + 0x30
m[i]=E2
v=m[i]
i++
}
이렇게 되겠습니다. 암호화루틴을 알았으니, 브루트포스코드를 작성해
암호화했을때 OO]oUU2U<sU2UsUsK 가 되는 문자열을 찾아보도록 하겠습니다
[python]
en="OO]oUU2U<sU2UsUsK"
m=""
l=len(en)
v=0x48
v2=0xea0ea0eb
def encode(d):
E1 = ((d + 0xc ) * v) + 0x11
E2 = ( (E1 * v2) >> 32 ) >> 6
E2 = E2 - (E1>>31)
E2 = ( E1 - (E2 * 0x46) ) + 0x30
return E2
for i in range(0,l):
for j in range(33,126):
temp=encode(j)
if chr(temp)==en[i]:
m+=chr(j)
v=temp
break
print(m)
코드를 돌려서 나온 문자열을 nc ctf.j0n9hyun.xyz 9004 에 입력하면 FLAG가 나온다!
[+추가]
handray
E1 = ( ( d + 0xc ) * v) + 0x11
E2 = ( (E1 * v2) >> 32 ) >> 6
E2 = E2 - (E1>>31)
E2 = ( E1 - (E2 * 0x46) ) + 0x30
Ghidra
E1 = ( ( d + 0xc ) * v ) + 0x11;
E2 = E1 + int(E1 / 0x46) * -0x46 + 0x30;
idapro ( 블로그참고 )
E2 = ( ( ( d + 0xc ) * v) + 0x11) % 0x46+0x30
이걸로
E1 + ( E * 0xea0ea0eb >> 32 >> 6 - E >> 31 * -0x46 )
= E1 + ( E1 / 0x46 * -0x46 )
= E1 % 0x46
인걸 알 수 있다..
[배운점]
handray 더 연습해야겠다.