Writeup
[Dreamhack] 리버싱 rev-basic-4 Writeup
이둥둥
2025. 2. 22. 02:32

지난 리버싱 시리즈와 마찬가지로 Correct값을 출력해주는
입력값을 찾는 문제다
바로 디컴파일해서 소스코드를 살펴보자
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[256]; // [rsp+20h] [rbp-118h] BYREF
memset(v4, 0, sizeof(v4));
sub_1400011C0("Input : ", argv, envp);
sub_140001220("%256s", v4);
if ( (unsigned int)sub_140001000(v4) )
puts("Correct");
else
puts("Wrong");
return 0;
}
__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 0LL;
}
return 1LL;
}
int 64 a1이 입력값을 저장하는 변수인것 같다
sub_140001000 함수에서 조건에 따라 비교해서 main 함수에서 correct를 출력한다
( ((unsigned __int8)(16 * *(_BYTE *)(a1 + i)) | ((int)*(unsigned __int8 *)(a1 + i) >> 4)) != byte_140003000[i] )
이 부분을 간소화해서 역연산하는게 관건인데

arr[i]=[0x24,0x27,0x13,0xC6,0xC6,0x13,0x16,0xE6,0x47,0xF5,0x26,0x96,0x47,0xF5,0x46,0x27,0x13,0x26,0x26,0xC6,0x56,0xF5,0xC3,0xC3,0xF5,0xE3,0xE3]
(16*a1[i] | a1[i]>>4) = arr[i]
(al[i]<<4 | al[i]>>4) = arr[i]
>> 이 기호는 비트 연산자이고 0010 0000 >> 4이면 0000 0010 이렇게 비트를 이동시킨다
이 코드의 의미 자체는 알겠는데 이 연산의 전체적인 흐름이 이해가 안돼서 결국 직접 계산을 해봤다..!

손으로 써서 해보니까 드디어 이해했다
상위4비트와 하위4비트의 위치를 스왑한 후 OR 연산을 한거구나 유레카
그럼 a1[i]를 되돌리려면 arr[i]에 있는 값들로 다시 비트 스왑부터 하면 되겠당
arr[1]의 값이 0010 0110 이라고 하면 원래 값은 0110 0010 일테니까
>>4한 값이랑 <<4이랑 OR을 하면 되는데 곰곰히 생각해보니까
OR 연산할 필요없이 그냥 더하기를 해도 같은 결과가 나오겠다는걸 발견함!
그리고 16*은 <<4랑 동일하다는걸 새로 배웠다


일단 각각 상위/하위 4비트를 추출하기 위해서 binary to hex를 계산했다
al[i]&F0→상위 4비트
arr = [0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 0x26, 0x96, 0x47, 0xF5, 0x46, 0x27,
0x13, 0x26, 0x26, 0xC6, 0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3]
flag=[]
for i in range(len(arr)):
value=((arr[i]&0xF0)>>4)+((arr[i]&0x0F)<<4)
flag.append(chr(value))
print(''.join(flag))
OR 연산자로 해도 되지만 반골기질이랄까 도전정신이 들어서 + 연산자로 코드를 작성했다 ^^

왜 이렇게 되는걸까 살펴보니까
print 함수가 for 문 안에 있어서 i횟수만큼 반복되는게 문제였다

플래그 발견!!
