반응형
rev-basic-7
__int64 __fastcall sub_140001000(__int64 a1)
{
int i; // [rsp+0h] [rbp-18h]
for ( i = 0; (unsigned __int64)i < 0x1F; ++i )
{
if ( (i ^ (unsigned __int8)__ROL1__(*(_BYTE *)(a1 + i), i & 7)) != byte_140003000[i] )
return 0i64;
}
return 1i64;
}
a1[i]
과(i&7)
을 ROL 연산- ROL 연산 결과를 i와 xor 연산
- 결과를
byte_140003000[i]
와 비교
핵심으로 알아야 하는 키워드는 ROL 연산이다.
○ ROL
쉽게 설명하면 left shift 연산이랑 비슷한데, 연산 수행 후에 기존 8자리를 벗어나게 되는 비트는 오른쪽 맨 끝 자리로 돌아오는 형태의 연산이다.
- shitf 연산인데 큐처럼 동작하는 shift 연산이라고 비유하면 될 것 같다.
XOR 연산의 경우는 양변을 i
로 XOR 연산해주면 되기 때문에 쉽게 해결할 수 있다.
XOR 연산을 수행하면 다음과 같은 식으로 표현할 수 있다.
(unsigned __int8)__ROL1__(*(_BYTE *)(a1 + i), i & 7)) != byte_140003000[i] ^ i
이제 ROL 연산을 역연산 할 수 있다면 flag를 구할 수 있다.
ROL의 역연산은 ROR 연산이다.
1. (unsigned __int8)__ROL1__(*(_BYTE *)(a1 + i), i & 7)) == byte_140003000[i] ^ i
// ROL -> ROR 로 변환
2. (unsigned __int8)__ROR1__(byte_140003000[i] ^ i, i & 7)) == *(_BYTE *)(a1 + i)
즉, 위와 같이 1번을 2번으로 바꿔서 표현할 수 있다.
def ror(n, m):
shift = n >> m
src = n << (8 - m)
src &= 255
return shift | src
ROR 연산을 수행하는 함수다.
코드 구성은 shift 연산 이후에 8자리를 벗어나는 값들을 차례로 왼쪽에 밀어 넣는 코드다.
a[]
를 구하기 위한 모든 조건을 알아냈으니, flag를 구해보자.
필자는 IDApython으로 풀었다.
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
arr = extract_byte_array(0x140003000, 32)
def ror(n, m):
shift = n >> m
src = n << (8 - m)
src &= 255
return shift | src
for i in range(len(arr)):
arg1 = arr[i] ^ i
print(chr(ror(arg1,i&7)), end = '')
print()
반응형