Decompiled-src
main
C++언어로 컴파일되있음. main에서 호출시키는 4가지 함수는 다음과 같았음.
- sub_12E0
- sub_18F0
- sub_2650
- sub_2850
__int64 __fastcall main(int a1, const char **a2, char **a3)
{
const char *v3; // rbx
signed __int64 v4; // rax
size_t v5; // r14
char *v6; // r15
const char *v7; // r15
size_t v8; // rax
_BYTE *v9; // r14
char v10; // al
std::ostream *v11; // rax
const char *v12; // rbx
size_t v13; // rax
__int64 v14; // rax
_BYTE *v15; // rbx
char v16; // al
std::ostream *v17; // rax
unsigned int v18; // ebx
__int64 v19; // rax
_BYTE *v20; // rbx
char v21; // al
void *v22; // rbx
_BYTE *v23; // r14
_QWORD *v24; // r15
_QWORD *v25; // rbp
unsigned __int64 v26; // rsi
unsigned int v27; // r8d
__int64 v28; // rdx
__int64 v29; // rax
__int64 v30; // rdi
__int64 v31; // rax
__int64 v32; // rdi
bool v33; // cf
__m128i *v34; // rbx
__m128i *v35; // r14
__m128i *v36; // r13
__m128i v37; // xmm0
__m128i v38; // xmm1
__m128i v39; // xmm2
__m128i *v40; // r15
__int64 v41; // r15
__int64 v42; // rax
__int64 v43; // r13
__m128i *v44; // r12
__int64 v45; // r15
__m128i v46; // xmm0
__m128i v47; // xmm1
__m128i v48; // xmm2
const __m128i *v49; // rax
__m128i v50; // xmm0
__m128i v51; // xmm1
__m128i v52; // xmm2
__m128i *v53; // r14
bool v54; // zf
std::ostream *v55; // rax
__int64 v57; // r8
__int64 v58; // r9
__int64 v59; // r10
__int64 v60; // r8
__int64 v61; // r8
int v62; // esi
char *v63; // r10
__int64 v64; // r11
__int64 v65; // rbx
__m128i v66; // xmm3
_QWORD *v67; // [rsp+0h] [rbp-118h]
void *v68; // [rsp+8h] [rbp-110h] BYREF
_QWORD *v69; // [rsp+10h] [rbp-108h]
__m128i v70; // [rsp+20h] [rbp-F8h] BYREF
__m128i v71; // [rsp+30h] [rbp-E8h] BYREF
__m128i v72; // [rsp+40h] [rbp-D8h] BYREF
__m128i v73; // [rsp+50h] [rbp-C8h] BYREF
_BYTE v74[64]; // [rsp+60h] [rbp-B8h] BYREF
void *v75[2]; // [rsp+A0h] [rbp-78h] BYREF
_QWORD v76[2]; // [rsp+B0h] [rbp-68h] BYREF
void *v77; // [rsp+C0h] [rbp-58h]
unsigned __int64 v78; // [rsp+C8h] [rbp-50h]
_QWORD dest[9]; // [rsp+D0h] [rbp-48h] BYREF
dest[2] = __readfsqword(0x28u);
if ( a1 == 2 )
{
v3 = a2[1];
v77 = dest;
if ( !v3 )
std::__throw_logic_error("basic_string::_M_construct null not valid");
v4 = strlen(v3);
v5 = v4;
v6 = (char *)dest;
if ( (unsigned __int64)v4 >= 0x10 )
{
if ( v4 < 0 )
std::__throw_length_error("basic_string::_M_create");
if ( v4 + 1 < 0 )
std::__throw_bad_alloc();
v6 = (char *)operator new(v4 + 1);
v77 = v6;
dest[0] = v5;
}
if ( v5 )
{
if ( v5 == 1 )
*v6 = *v3;
else
memcpy(v6, v3, v5);
}
v78 = v5;
v6[v5] = 0;
if ( v78 <= 2 )
{
std::__ostream_insert<char,std::char_traits<char>>(&std::cerr, "Invalid hex-string", 18);
v19 = *(_QWORD *)(std::cerr - 24LL);
v20 = *(_BYTE **)((char *)&std::cerr + v19 + 240);
if ( !v20 )
std::__throw_bad_cast();
if ( v20[56] )
{
v21 = v20[67];
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)&std::cerr + v19 + 240));
v21 = (*(__int64 (__fastcall **)(_BYTE *, __int64))(*(_QWORD *)v20 + 48LL))(v20, 10);
}
v55 = (std::ostream *)std::ostream::put((std::ostream *)&std::cerr, v21);
v18 = 1;
std::ostream::flush(v55);
LABEL_72:
if ( v77 != dest )
operator delete(v77);
return v18;
}
v22 = (void *)(v78 - 2);
v75[0] = v76;
v23 = (char *)v77 + 2;
if ( v78 - 2 < 0x10 )
{
v24 = v76;
if ( v78 == 3 )
{
LOBYTE(v76[0]) = *v23;
v24 = v76;
goto LABEL_37;
}
}
else
{
if ( (__int64)v22 < 0 )
std::__throw_length_error("basic_string::_M_create");
if ( (__int64)(v78 - 1) < 0 )
std::__throw_bad_alloc();
v24 = (_QWORD *)operator new(v78 - 1);
v75[0] = v24;
v76[0] = v22;
}
memcpy(v24, v23, (size_t)v22);
LABEL_37:
v75[1] = v22;
*((_BYTE *)v22 + (_QWORD)v24) = 0;
sub_12E0(&v68, v75);
v25 = v68;
v67 = v69;
v26 = (unsigned __int64)((char *)v69 - (_BYTE *)v68) >> 3;
v27 = v26 - 1;
if ( (int)v26 - 1 > 0 )
{
v28 = v27;
v29 = (unsigned int)v26;
if ( v27 < 0x22
|| (v57 = (unsigned int)(v26 - 2), v58 = 8 * v28 - 8, (char *)v68 + 8 * v57 - v58 > (char *)v68 + 8 * v57)
|| (char *)v68 + 8 * v28 - v58 > (char *)v68 + 8 * v28
|| (unsigned int)v57 < (int)v28 - 1
|| (unsigned __int64)(v28 - 1) >> 32
|| (v59 = 8 * v28, v60 = ((char *)v69 - (_BYTE *)v68 + 0x7FFFFFFF0LL) & 0x7FFFFFFF8LL, v68 < (char *)v68 + v60)
&& (char *)v68 + v60 - v59 + 8 < (char *)v68 + 8 * v28 + 8 )
{
v30 = v28;
}
else
{
v61 = v28 & 0x7FFFFFFC;
v29 = (unsigned int)v26 - v61;
v30 = v28 & 3;
v62 = v26 - 2;
v63 = (char *)v68 + v59 - 8;
v64 = 0;
do
{
v65 = (unsigned int)(v62 + v64);
v66 = _mm_xor_si128(
_mm_xor_si128(_mm_loadu_si128((const __m128i *)&v63[8 * v64 - 16]), (__m128i)-1LL),
_mm_loadu_si128((const __m128i *)&v25[v65 - 3]));
*(__m128i *)&v63[8 * v64] = _mm_xor_si128(
_mm_xor_si128(_mm_loadu_si128((const __m128i *)&v63[8 * v64]), (__m128i)-1LL),
_mm_loadu_si128((const __m128i *)&v25[v65 - 1]));
*(__m128i *)&v63[8 * v64 - 16] = v66;
v64 -= 4;
}
while ( -(v28 & 0x7FFFFFFC) != v64 );
if ( v61 == v28 )
goto LABEL_42;
}
v31 = v29 + 4294967294LL;
v32 = v30 + 1;
do
{
v25[v32 - 1] = ~(v25[v32 - 1] ^ v25[(unsigned int)v31--]);
v33 = v32-- == 1;
}
while ( !v33 && v32 != 1 );
}
LABEL_42:
if ( v25 != v67 )
{
v34 = 0;
v35 = 0;
v36 = 0;
do
{
while ( 1 )
{
sub_18F0(*v25, v74);
sub_2650(&v70, v74);
if ( v35 == v36 )
break;
v37 = _mm_loadu_si128(&v70);
v38 = _mm_loadu_si128(&v71);
v39 = _mm_loadu_si128(&v72);
v35[3] = _mm_loadu_si128(&v73);
v35[2] = v39;
v35[1] = v38;
*v35 = v37;
v40 = v35;
v35 += 4;
if ( ++v25 == v67 )
goto LABEL_60;
}
if ( (char *)v35 - (char *)v34 == 0x7FFFFFFFFFFFFFC0LL )
std::__throw_length_error("vector::_M_realloc_insert");
v41 = ((char *)v35 - (char *)v34) >> 6;
v42 = (v41 == 0) + v41;
v43 = v42 + v41;
if ( (unsigned __int64)(v42 + v41) >= 0x1FFFFFFFFFFFFFFLL )
v43 = 0x1FFFFFFFFFFFFFFLL;
if ( __CFADD__(v41, v42) )
v43 = 0x1FFFFFFFFFFFFFFLL;
if ( v43 )
v44 = (__m128i *)operator new(v43 << 6);
else
v44 = 0;
v45 = v41 << 6;
v46 = _mm_loadu_si128(&v70);
v47 = _mm_loadu_si128(&v71);
v48 = _mm_loadu_si128(&v72);
*(__m128i *)((char *)&v44[3] + v45) = _mm_loadu_si128(&v73);
*(__m128i *)((char *)&v44[2] + v45) = v48;
*(__m128i *)((char *)&v44[1] + v45) = v47;
*(__m128i *)((char *)v44 + v45) = v46;
v40 = v44;
if ( v34 != v35 )
{
v40 = v44;
v49 = v34;
do
{
v50 = _mm_loadu_si128(v49);
v51 = _mm_loadu_si128(v49 + 1);
v52 = _mm_loadu_si128(v49 + 2);
v40[3] = _mm_loadu_si128(v49 + 3);
v40[2] = v52;
v40[1] = v51;
*v40 = v50;
v49 += 4;
v40 += 4;
}
while ( v49 != v35 );
}
if ( v34 )
operator delete(v34);
v36 = &v44[4 * v43];
v34 = v44;
v35 = v40 + 4;
++v25;
}
while ( v25 != v67 );
LABEL_60:
if ( v34 != v35 )
{
v53 = v34;
do
{
sub_2850(v53);
v54 = v53 == v40;
v53 += 4;
}
while ( !v54 );
}
if ( v34 )
operator delete(v34);
}
if ( v68 )
operator delete(v68);
if ( v75[0] != v76 )
operator delete(v75[0]);
v18 = 0;
goto LABEL_72;
}
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, "Usage: ", 7);
v7 = *a2;
if ( *a2 )
{
v8 = strlen(*a2);
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, v7, v8);
}
else
{
std::ios::clear(
(char *)&std::cout + *(_QWORD *)(std::cout - 24LL),
*(_DWORD *)((char *)&std::cout + *(_QWORD *)(std::cout - 24LL) + 32) | 1u);
}
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, " {hex-string}", 13);
v9 = *(_BYTE **)((char *)&std::cout + *(_QWORD *)(std::cout - 24LL) + 240);
if ( !v9 )
goto LABEL_88;
if ( v9[56] )
{
v10 = v9[67];
}
else
{
std::ctype<char>::_M_widen_init(v9);
v10 = (*(__int64 (__fastcall **)(_BYTE *, __int64))(*(_QWORD *)v9 + 48LL))(v9, 10);
}
v11 = (std::ostream *)std::ostream::put((std::ostream *)&std::cout, v10);
std::ostream::flush(v11);
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, "Example: ", 9);
v12 = *a2;
if ( *a2 )
{
v13 = strlen(v12);
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, v12, v13);
}
else
{
std::ios::clear(
(char *)&std::cout + *(_QWORD *)(std::cout - 24LL),
*(_DWORD *)((char *)&std::cout + *(_QWORD *)(std::cout - 24LL) + 32) | 1u);
}
std::__ostream_insert<char,std::char_traits<char>>(&std::cout, " 0x3E08080818381808", 19);
v14 = *(_QWORD *)(std::cout - 24LL);
v15 = *(_BYTE **)((char *)&std::cout + v14 + 240);
if ( !v15 )
LABEL_88:
std::__throw_bad_cast();
if ( v15[56] )
{
v16 = v15[67];
}
else
{
std::ctype<char>::_M_widen_init(*(_QWORD *)((char *)&std::cout + v14 + 240));
v16 = (*(__int64 (__fastcall **)(_BYTE *, __int64))(*(_QWORD *)v15 + 48LL))(v15, 10);
}
v17 = (std::ostream *)std::ostream::put((std::ostream *)&std::cout, v16);
std::ostream::flush(v17);
return 1;
}
Run
실행시 아래와 같이 매개변수 16진수를 요구함.
seo@seo:~/study/hto2025/barcode$ ./barcode
Usage: ./barcode {hex-string}
Example: ./barcode 0x3E08080818381808
매개변수 8바이트일 경우, 별 아스키 아트가 8줄 출력됨.
./barcode 0x4142434445464748
seo@seo:~/study/hto2025/barcode$ ./barcode 0x4142434445464748 * * *** * ** * * * * * * ** * * * * *
16바이트인 경우, 별 아스키 아트가 16줄 출력됨.
./barcode 0x4142434445464748abadbabe13371338
seo@seo:~/study/hto2025/barcode$ ./barcode 0x4142434445464748abadbabe13371338
* *
*** *
** *
* * *
* *
** *
* *
* *
**** *
** * * *
*** *
* * * *
* *
**
*
* * *
그렇다면, flag.barcode는 매개변수가 32바이트여야함.
ex) ./barcode 0x4142434445464748abadbabedeadbeef1337c0de5152535455565758
cat flag.barcode
seo@seo:~/study/hto2025/barcode$ cat flag.barcode ****** * ****** * * * * * * * * ****** **** * * ****** * * * * * * **** * * * * *** * * ****
main에서 호출시키는 4가지 함수를 차례대로 살펴보자.
매개변수는 0x000000004142434445464748abadbabedeadbeef1337c0de5152535455565758 으로 우선 넣어주었다.
sub_12E0(__int64 a1, __int64 a2)
- 호출 전
rdi = 00007FFFFFFFE0E8
MEMORY:00007FFFFFFFE0E8 dq 0
rsi = 00007FFFFFFFE180
MEMORY:00007FFFFFFFE180 dq offset off_55555556BF00 ... MEMORY:000055555556BF00 a41424344454647 db '4142434445464748abadbabedeadbeef1337c0de5152535455565758',0
- 호출 후
rdi = 7rsi = 000055555555A010
MEMORY:000055555555A010 dq offset unk_2000000000003
sub_18F0(__int64 a1, _BYTE *a2)
- 호출 전
rdi = 0000000041424344rsi = 00007FFFFFFFE140
MEMORY:00007FFFFFFFE140 db 2, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE148 db 6, 0, 0, 0, 0, 0, 0, 80h MEMORY:00007FFFFFFFE150 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE158 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE160 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE168 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE170 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE178 db 0, 0, 0, 0, 0, 0, 0, 0
- 호출 후
rdi 값에 의해 64바이트 크기의 배열이 생성됨.
rdi = 0rsi = 00007FFFFFFFE140
MEMORY:00007FFFFFFFE140 db 0, 0, 1, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE148 db 1, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE150 db 0, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE158 db 1, 0, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE160 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE168 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE170 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE178 db 0, 0, 0, 0, 0, 0, 0, 0
sub_2650(_BYTE *a1, _BYTE *a2)
- 호출 전
rdi = 00007FFFFFFFE100
MEMORY:00007FFFFFFFE100 dq offset off_7FFFF7E2A000 ... MEMORY:00007FFFF7E2A000 off_7FFFF7E2A000 dq offset off_7FFFF7E24318 ... MEMORY:00007FFFF7E24318 off_7FFFF7E24318 dq offset off_7FFFF7D4FA30 ... MEMORY:00007FFFF7D4FA30 off_7FFFF7D4FA30 dq offset unk_89485355FA1E0FF3
rsi = 00007FFFFFFFE140
MEMORY:00007FFFFFFFE140 db 0, 0, 1, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE148 db 1, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE150 db 0, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE158 db 1, 0, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE160 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE168 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE170 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE178 db 0, 0, 0, 0, 0, 0, 0, 0
- 호출 후
rdi = 00007FFFFFFFE100
MEMORY:00007FFFFFFFE100 db 0, 0, 1, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE108 db 1, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE110 db 0, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE118 db 1, 0, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE120 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE128 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE130 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE138 db 0, 0, 0, 0, 0, 0, 0, 0
rsi = 00007FFFFFFFE140
MEMORY:00007FFFFFFFE140 db 0, 0, 1, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE148 db 1, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE150 db 0, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE158 db 1, 0, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE160 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE168 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE170 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE178 db 0, 0, 0, 0, 0, 0, 0, 0
64바이트 크기의 배열 값이 a1에 복사됨.
이후 while(1) 루프문에 의해 계속 sub_18F0, sub_2650 함수가 호출됨.
sub_18F0(__int64 a1, _BYTE *a2) (2트)
마찬가지로 BAB9B8B715100605 값에 의해 64바이트 크기의 배열이 생성됨.
- 호출 전
RDI = BAB9B8B715100605RSI = 00007FFFFFFFE140
MEMORY:00007FFFFFFFE140 db 0, 0, 1, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE148 db 1, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE150 db 0, 1, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE158 db 1, 0, 0, 0, 0, 0, 1, 0 MEMORY:00007FFFFFFFE160 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE168 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE170 db 0, 0, 0, 0, 0, 0, 0, 0 MEMORY:00007FFFFFFFE178 db 0, 0, 0, 0, 0, 0, 0, 0
그럼, BAB9B8B715100605저 값은 그럼 어떻게 나온걸까?
main 함수 중 아래 코드, XOR과 NOR 연산시키는 반복문에 브포 걸어봄.
do
{
v25[v32 - 1] = ~(v25[v32 - 1] ^ v25[(unsigned int)v31--]);
v33 = v32-- == 1;
}
while ( !v33 && v32 != 1 );
1트:
어셈 코드:
.text:0000000000001F27 xor rcx, [rbp+rdi*8-8]
실행 전
rcx = DEADBEEF1337C0DE[rbp+rdi*8-8] = 000055555556C068
MEMORY:000055555556C068 dq offset unk_5152535455565758
실행 후
rcx = 8FFFEDBB46619786
어셈 코드:
.text:0000000000001F2C not rcx
실행 후
rcx = 70001244B99E6879
2트:
어셈 코드:
.text:0000000000001F27 xor rcx, [rbp+rdi*8-8]
실행 전
rcx = 0x45464748ABADBABE[rbp+rdi*8-8] = 000055555556C060
MEMORY:000055555556C060 dq offset unk_DEADBEEF1337C0DE
실행 후
rcx = 9BEBF9A7B89A7A60
어셈 코드:
.text:0000000000001F2C not rcx
실행 후
rcx = 641406584765859F
3트:
어셈 코드:
.text:0000000000001F27 xor rcx, [rbp+rdi*8-8]
실행 전
rcx = 0x0000000041424344[rbp+rdi*8-8] = 000055555556C058
MEMORY:000055555556C058 dq offset unk_45464748ABADBABE
실행 후
rcx = 0x45464748EAEFF9FA
어셈 코드:
.text:0000000000001F2C not rcx
실행 후
rcx = 0xBAB9B8B715100605
여기서 BAB9B8B715100605 값이 나왔다.
즉, 0x0000000041424344와 45464748ABADBABE이 XOR하고 NOT연산되어 나온것.
>>> hex(~(0x0000000041424344 ^ 0x45464748ABADBABE) & 0xffffffffffffffff) '0xbab9b8b715100605'
XOR과 NOT 연산 반복문이 끝나면, 아래 값들이 sub_18F0 호출전 RDI로 지정됨.
MEMORY:000055555556C050 dq offset unk_41424344 MEMORY:000055555556C058 dq offset unk_BAB9B8B715100605 MEMORY:000055555556C060 dq offset unk_641406584765859F MEMORY:000055555556C068 dq offset unk_70001244B99E6879 MEMORY:000055555556C070 dq 0
0x000000004142434445464748abadbabedeadbeef1337c0de5152535455565758
8바이트씩 나누면 다음과 같은데, 각각 a, b, c, d로 명명하겠음.
- 0x0000000041424344 → a
- 0x45464748abadbabe → b
- 0xdeadbeef1337c0de → c
- 0x5152535455565758 → d
아래와 같이 계산되었다고 볼 수 있음.
0x0000000041424344 → 0x0000000041424344
0xBAB9B8B715100605 → hex(~(a ^ b) & 0xffffffffffffffff)
0x641406584765859F → hex(~(b ^ c) & 0xffffffffffffffff)
0x70001244B99E6879
→ hex(~(c ^ d) & 0xffffffffffffffff)
재구현
32바이트 크기의 매개변수값이 XOR/NOT 연산되어, 64바이트 배열들이 4번 나오는 코드를 재구현시키면 아래와 같음.
sub_18F0 함수는 64개 비트 저장할 리스트 생성하고, n번째 비트를 추출하여 저장시킴.
- barcode_reimpl.py
value = 0x000000004142434445464748abadbabedeadbeef1337c0de5152535455565758
hex_str = f"{value:064x}"
a = int(hex_str[0:16], 16)
b = int(hex_str[16:32], 16)
c = int(hex_str[32:48], 16)
d = int(hex_str[48:64], 16)
print(f"a = 0x{a:016x}")
print(f"b = 0x{b:016x}")
print(f"c = 0x{c:016x}")
print(f"d = 0x{d:016x}")
_a = a
_b = ~(a ^ b) & 0xffffffffffffffff
_c = ~(b ^ c) & 0xffffffffffffffff
_d = ~(c ^ d) & 0xffffffffffffffff
a=_a
b=_b
c=_c
d=_d
print("XOR/NOT loop calculated")
print(f"a = 0x{a:016x}")
print(f"b = 0x{b:016x}")
print(f"c = 0x{c:016x}")
print(f"d = 0x{d:016x}")
def sub_18F0(a1: int):
a2 = [0] * 64
for i in range(64):
a2[i] = ((a1 >> i) & 1) # i번째 비트를 추출하여 저장
return a2
def pretty_print(bits: list[int]):
output = ""
for i in range(64):
if i % 8 == 0 and i != 0:
output += "\n" # 8비트마다 줄바꿈
output += "*" if bits[i] else " "
print(output)
for val in (a, b, c, d):
r = sub_18F0(val)
pretty_print(r)
- Result
PS C:\Users\seo\Desktop\핵테온\핵테온_2025\barcode> python3 .\barcode_reimpl.py
a = 0x0000000041424344
b = 0x45464748abadbabe
c = 0xdeadbeef1337c0de
d = 0x5152535455565758
XOR/NOT loop calculated
a = 0x0000000041424344
b = 0xbab9b8b715100605
c = 0x641406584765859f
d = 0x70001244b99e6879
* *
** *
* *
* *
* *
**
*
* * *
*** ** *
*** *
* *** *
* *** *
***** *
* * *
* * **
*** *
** *
**
* *
* **
* ****
* **
**** *
* *** *
* *
* *
***
solve.py
- 먼저 flag.barcode 파일을 파싱하여 8바이트 align 시켜 각 배열로 저장. (
barcode_array2차원 리스트 생성됨) calculated_val변수를 통해 인덱스 별로 0x0~0xFF 범위의 한 바이트씩 바꿨을때,get_star_result결과의 한 배열과 같을 경우, 다음 인덱스 진행.
def parse_barcode_file(filename):
result = []
with open(filename, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
line = line.rstrip('\n')
# 빈 줄이면 8개의 0으로 채운 행 추가
if not line.strip():
result.append([0] * 8)
continue
row = []
for ch in line:
if ch == '*':
row.append(1)
elif ch == ' ':
row.append(0)
result.append(row)
return result
barcode_array = parse_barcode_file('flag.barcode')
# print(barcode_array)
def edit_byte(v: int, idx: int, b: int, size: int = 32) -> int:
"""
v : 수정할 정수
idx : 0부터 시작하는 바이트 인덱스 (0 = 최상위 바이트)
b : 대체할 새 바이트 값 (0–255)
size : 전체 바이트 길이 (기본 32바이트)
"""
ba = bytearray(v.to_bytes(size, 'big'))
ba[idx] = b & 0xFF
return int.from_bytes(ba, 'big')
def get_star_result(value):
hex_str = f"{value:064x}"
a = int(hex_str[0:16], 16)
b = int(hex_str[16:32], 16)
c = int(hex_str[32:48], 16)
d = int(hex_str[48:64], 16)
_a = a
_b = ~(a ^ b) & 0xffffffffffffffff
_c = ~(b ^ c) & 0xffffffffffffffff
_d = ~(c ^ d) & 0xffffffffffffffff
a=_a
b=_b
c=_c
d=_d
def sub_18F0(a1: int):
a2 = [0] * 64
for i in range(64):
a2[i] = ((a1 >> i) & 1)
return a2
all_data = []
for val in (a, b, c, d):
r = sub_18F0(val)
all_data += r
grouped = [all_data[i:i+8] for i in range(0, len(all_data), 8)]
return grouped
def get_a_b_c_d(value):
value = f"{calculated_val:064x}"
while len(value) < 64:
value = '0' + value
a = int(value[0:16], 16)
b = int(value[16:32], 16)
c = int(value[32:48], 16)
d = int(value[48:64], 16)
return a, b, c, d
value, a, b, c, d = 0, 0, 0, 0, 0
calculated_val = value
def decrypt_hex(start_idx, end_idx):
global calculated_val
for i in range(8):
for j in range(0x0, 0x100):
calculated_val = edit_byte(calculated_val, end_idx - i, j)
star_group = get_star_result(calculated_val)
if(star_group[i + start_idx] == barcode_array[i + start_idx]):
break
decrypt_hex(0, 7)
decrypt_hex(8, 15)
decrypt_hex(16, 23)
decrypt_hex(24, 31)
a, b, c, d = get_a_b_c_d(calculated_val)
print(f"0x{calculated_val:064x}")
Result
PS C:\Users\seo\Desktop\핵테온\핵테온_2025\barcode> python3 .\solve.py 0x000202027e027e00ff83ffff83ff83ff003e424202424000fffdffcfffff83ff