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 = 7
rsi = 000055555555A010
MEMORY:000055555555A010 dq offset unk_2000000000003
sub_18F0(__int64 a1, _BYTE *a2)
- 호출 전
rdi = 0000000041424344
rsi = 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 = 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
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 = BAB9B8B715100605
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
그럼, 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_array
2차원 리스트 생성됨) 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