반응형
rev-basic-4
__int64 __fastcall sub_140001000(__int64 a1)
{
int i; // [rsp+0h] [rbp-18h]
for ( i = 0; (unsigned __int64)i < 0x1C; ++i )
{
if ( ((unsigned __int8)(16 * *(_BYTE *)(a1 + i)) | ((int)*(unsigned __int8 *)(a1 + i) >> 4)) != byte_140003000[i] )
return 0i64;
}
return 1i64;
}
if문 조건으로 a1에 대한 검증을 수행한다.
조건을 해석하면 다음과 같다.
(16 * a1[i]) ^ (a1[i] >> 4) == byte_140003000[i]
16*a1[i]
과 a1[i] >> 4
를 서로 OR 연산한 결과를 생성한다.
앞서 생성한 결과와 byte_140003000[i]
가 동일한 경우의 a1[i]
이 flag다.
즉, flag를 구하는 방법의 핵심은 16*a1[i]
에 있다. 2⁴*a1[i]
은 a1[i] << 4
와 수학적으로 같은 의미다.
그렇다면 다음과 같이 식을 바꿀 수 있다.
변경 전: (16 * a1[i]) ^ (a1[i] >> 4) == byte_140003000[i]
변경 후: (a1[i] << 4) ^ (a1[i] >> 4) == byte_140003000[i]
a1[i] << 4
와 a1[i] >> 4
를 각각 2진수로 바꾸면 다음과 같이 표현이 가능하다.
a1[i] << 4 = [aaaa 0000]
a1[i] >> 4 = [0000 bbbb]
2개의 결과를 OR 연산하면 [aaaa bbbb] = byte_140003000[i]
가 될 것이다.
요약하면 다음과 같이 정리할 수 있다.
a1[i] = aaaa bbbb 라고 가정하면, byte_140003000[i] = bbbb aaaa가 된다!
결론적으로 byte_140003000[i]
를 2진수로 표현하고 상위 4비트와 하위 4비트의 위치를 바꿔서 계산하면 된다.
필자는 IDA python을 이용했다.
import idc
def extract_byte_array(start_address, length):
extracted_data = []
for i in range(length):
byte_value = idc.get_wide_byte(start_address + i)
extracted_data.append(byte_value)
return extracted_data
data = extract_byte_array(0x140003000, 28)
result = ''
for i in data:
temp = format(i, "b").zfill(8)
x = temp[:4]
y = temp[4:]
temp = y+x
temp = int(temp, 2)
result += chr(temp)
print(result)
반응형