ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (626)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (13)
      • dreamhack (12)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk
CTF

vsCTF 2023

vsCTF 2023
CTF

vsCTF 2023

2023. 9. 25. 18:44

 

이번에도 리버싱 하나 풀었습니다.

 


 


REV

x0rr3al?!!

더보기

IDA로 디컴파일합니다.

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char v4; // [rsp+Fh] [rbp-51h]
  int i; // [rsp+10h] [rbp-50h]
  int v6; // [rsp+14h] [rbp-4Ch]
  char s[56]; // [rsp+20h] [rbp-40h] BYREF
  unsigned __int64 v8; // [rsp+58h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  if ( (unsigned int)sub_17A4(a1, a2, a3) )
  {
    sub_16AD();
    exit(1);
  }
  if ( ptrace(PTRACE_TRACEME, 0LL, 1LL, 0LL) == -1 )
  {
    sub_16AD();
    exit(1);
  }
  v6 = sub_1483(main, 512LL);
  sub_1355();
  sub_13F8();
  if ( v6 != (unsigned int)sub_1483(main, 512LL) )
  {
    sub_16AD();
    exit(1);
  }
  printf("p4ss m3 th3 fl4g: ");
  __isoc99_scanf("%53s", s);
  if ( strlen(s) == 53 )
  {
    for ( i = 0; i <= 52; ++i )
    {
      v4 = sub_150A(s[i], 0);
      if ( (unsigned int)sub_14F7(v4) != dword_40A0[i] )
        goto LABEL_8;
      if ( v6 != (unsigned int)sub_1483(main, 512LL) )
      {
        sub_16AD();
        exit(1);
      }
    }
    sub_1614();
    return 0LL;
  }
  else
  {
LABEL_8:
    sub_156A();
    return 0LL;
  }
}

 

main 함수에서 중요하게 봐야 할 코드는 다음과 같습니다.

...
if ( (unsigned int)sub_17A4(a1, a2, a3) )
  {
    sub_16AD();
    exit(1);
  }
if ( ptrace(PTRACE_TRACEME, 0LL, 1LL, 0LL) == -1 )
  {
    sub_16AD();
    exit(1);
  }
...
if ( v6 != (unsigned int)sub_1483(main, 512LL) )
  {
    sub_16AD();
    exit(1);
  }
...
  printf("p4ss m3 th3 fl4g: ");
  __isoc99_scanf("%53s", s);
  if ( strlen(s) == 53 )
  {
    for ( i = 0; i <= 52; ++i )
    {
      v4 = sub_150A(s[i], 0);
      if ( (unsigned int)sub_14F7(v4) != dword_40A0[i] )
        goto LABEL_8;
      if ( v6 != (unsigned int)sub_1483(main, 512LL) )
      {
        sub_16AD();
        exit(1);
      }
...

 

처음에 나오는 3개의 if문은 동적 디버깅으로 가볍게 우회해 줍니다.
(심볼이 없기 때문에 ida로 오프셋 참고해서 브포 걸고 ni 갈기면서 한 줄씩 봐야함..)

gdb로 디버깅 해보니 3개의 if 문은 각각 다음과 같은 곳에 있었습니다.
(set 명령으로 우회 가능) 

pwndbg> x/2i 0x00005555555559c9
   0x5555555559c9:	test   eax,eax
   0x5555555559cb:	je     0x5555555559e1

pwndbg> x/2i 0x00005555555559ff
   0x5555555559ff:	cmp    rax,0xffffffffffffffff
   0x555555555a03:	jne    0x555555555a19

pwndbg> x/2i 0x0000555555555a5d
   0x555555555a5d:	cmp    DWORD PTR [rbp-0x4c],eax
   0x555555555a60:	je     0x555555555a76

 

다음으로 플래그를 입력하고 검증하는 구문입니다. 

printf("p4ss m3 th3 fl4g: ");
__isoc99_scanf("%53s", s);
if ( strlen(s) == 53 )
{
  for ( i = 0; i <= 52; ++i )
  {
    v4 = sub_150A(s[i], 0);
    if ( (unsigned int)sub_14F7(v4) != dword_40A0[i] )
      goto LABEL_8;
    if ( v6 != (unsigned int)sub_1483(main, 512LL) )
    {
      sub_16AD();
      exit(1);
    }

 

먼저 입력 값의 길이는 53이 되어야 합니다.
다음으로 다음과 같은 식을 만족해야합니다.

for ( i = 0; i <= 52; ++i )
{
    v4 = sub_150A(s[i], 0);
    if ( (unsigned int)sub_14F7(v4) != dword_40A0[i] )
    if ( v6 != (unsigned int)sub_1483(main, 512LL) )
}

 

역연산을 위해 거꾸로 살펴보겠습니다.
v6을 검사하는 구문은 위의 3개의 if문 중 마지막 세 번째 if문을 우회할 때 설정한 값으로 인해 자동 통과입니다.

sub_14F7 함수는 다음과 같습니다. 

__int64 __fastcall sub_14F7(int a1)
{
  return a1 ^ 0x12u;
}

 

비교하는 값의 배열인 dword_40A0은 다음과 같습니다. 

pwndbg> x/55wx 0x5555555580a0
0x5555555580a0:	0x0000007e	0x0000007b	0x0000006b	0x0000007c
0x5555555580b0:	0x0000006e	0x00000073	0x0000007f	0x0000003b
0x5555555580c0:	0x0000003c	0x00000063	0x00000057	0x0000003c
0x5555555580d0:	0x00000066	0x0000007c	0x00000039	0x00000057
0x5555555580e0:	0x0000006c	0x0000003b	0x0000006a	0x0000007d
0x5555555580f0:	0x0000006f	0x0000006f	0x0000003b	0x0000007a
0x555555558100:	0x0000007b	0x00000057	0x0000003c	0x0000007a
0x555555558110:	0x0000003b	0x00000057	0x00000066	0x00000038
0x555555558120:	0x00000057	0x00000065	0x0000003c	0x0000007c
0x555555558130:	0x0000006b	0x00000060	0x00000057	0x0000006e
0x555555558140:	0x00000038	0x0000007a	0x00000057	0x0000007c
0x555555558150:	0x00000060	0x0000003b	0x00000057	0x0000003b
0x555555558160:	0x00000039	0x0000003b	0x0000003b	0x0000003f
0x555555558170:	0x00000075	0x00000000	0x00000000

 

다음으로 sub_150A 함수는 다음과 같습니다.

__int64 __fastcall sub_150A(unsigned __int8 a1, int a2)
{
  if ( a2 <= 3 )
    return (unsigned __int8)sub_150A(dest[11 * a2] ^ a1, a2 + 1);
  else
    return a1;
}

재귀 함수인 것을 확인했습니다.
dest 배열은 char 타입으로 다음과 같습니다. 

.bss:0000000000004180 ; char dest[10]
.bss:0000000000004180 dest            db 0Ah dup(?)           ; DATA XREF: sub_1355+F↑o
.bss:0000000000004180                                         ; sub_1355+22↑o ...
.bss:000000000000418A ; char byte_418A[10]
.bss:000000000000418A byte_418A       db 0Ah dup(?)           ; DATA XREF: sub_1355+35↑o
.bss:000000000000418A                                         ; sub_1355+48↑o
.bss:0000000000004194 ; char byte_4194[10]
.bss:0000000000004194 byte_4194       db 0Ah dup(?)           ; DATA XREF: sub_1355+5B↑o
.bss:0000000000004194                                         ; sub_1355+6E↑o
.bss:000000000000419E ; char byte_419E[10]
.bss:000000000000419E byte_419E       db 0Ah dup(?)           ; DATA XREF: sub_1355+81↑o
.bss:000000000000419E                                         ; sub_1355+94↑o

10개만 넣으면 out of index가 발생할테니 넉넉하게 60개 정도 찾아줍니다.

pwndbg> x/60cx 0x555555558180
0x555555558180:	0x73	0x33	0x63	0x52	0x33	0x74	0x73	0x33
0x555555558188:	0x00	0x00	0x76	0x73	0x63	0x74	0x66	0x76
0x555555558190:	0x73	0x63	0x74	0x69	0x69	0x61	0x6d	0x66
0x555555558198:	0x72	0x6e	0x6f	0x77	0x30	0x6b	0x6b	0x65
0x5555555581a0:	0x79	0x77	0x30	0x77	0x6b	0x65	0x79	0x77
0x5555555581a8:	0x77	0x6b	0x65	0x79	0x77	0x00	0x65	0x79
0x5555555581b0:	0x77	0x30	0x77	0x6b	0x65	0x79	0x77	0x00
0x5555555581b8:	0x00	0x00	0x00	0x00

 

역연산을 위해 거꾸로 살펴봤지만 모든 연산이 xor 연산이기 때문에

순서에 상관없이 동일한 연산을 수행하면 플래그를 복원할 수 있습니다.

dest = [0x73,0x33,0x63,0x52,0x33,0x74,0x73,0x33
,0x00,0x00,0x76,0x73,0x63,0x74,0x66,0x76
,0x73,0x63,0x74,0x69,0x69,0x61,0x6d,0x66
,0x72,0x6e,0x6f,0x77,0x30,0x6b,0x6b,0x65
,0x79,0x77,0x30,0x77,0x6b,0x65,0x79,0x77
,0x77,0x6b,0x65,0x79,0x77,0x00,0x65,0x79
,0x77,0x30,0x77,0x6b,0x65,0x79,0x77,0x00
,0x00,0x00,0x00,0x00]

def sub_150A(a1,a2):
  if a2 <= 3:
    return sub_150A(dest[11 * a2] ^ a1, a2 + 1)
  else:
    return a1

v2=[0x0000007e,0x0000007b,0x0000006b,0x0000007c
,0x0000006e,0x00000073,0x0000007f,0x0000003b
,0x0000003c,0x00000063,0x00000057,0x0000003c
,0x00000066,0x0000007c,0x00000039,0x00000057
,0x0000006c,0x0000003b,0x0000006a,0x0000007d
,0x0000006f,0x0000006f,0x0000003b,0x0000007a
,0x0000007b,0x00000057,0x0000003c,0x0000007a
,0x0000003b,0x00000057,0x00000066,0x00000038
,0x00000057,0x00000065,0x0000003c,0x0000007c
,0x0000006b,0x00000060,0x00000057,0x0000006e
,0x00000038,0x0000007a,0x00000057,0x0000007c
,0x00000060,0x0000003b,0x00000057,0x0000003b
,0x00000039,0x0000003b,0x0000003b,0x0000003f
,0x00000075]

for i in range(len(v2)):
  v2[i] = v2[i] ^ 0x12
  v2[i] = sub_150A(v2[i],0)
  print(chr(v2[i]),end='')
vsctf{w34k_4nt1_d3bugg3rs_4r3_n0_m4tch_f0r_th3_31337}

'CTF' 카테고리의 다른 글

osu!gaming CTF 2024  (0) 2024.03.04
TetCTF 2024  (0) 2024.01.29
CSAW CTF Qualification Round 2023  (0) 2023.09.18
SECCON CTF 2023 Quals  (0) 2023.09.17
BDSec CTF 2023  (0) 2023.07.22
  • REV
'CTF' 카테고리의 다른 글
  • osu!gaming CTF 2024
  • TetCTF 2024
  • CSAW CTF Qualification Round 2023
  • SECCON CTF 2023 Quals
ssongk
ssongk
벌레 사냥꾼이 되고 싶어요

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.