๐Ÿ”ธ[๋‚ด๋ถ€CTF2025-pwn]Forty-Seven-Bells
๐Ÿ’ก ๋ฌธ์ œ ์ถœ์ฒ˜
๋ฌธ์ œ ๊ตฌ์กฐ
C:.
โ”‚  Dockerfile
โ”‚  flag
โ”‚  get-docker.sh
โ”‚  libprob.so
โ”‚  prob
โ”‚  
โ”œโ”€for_user
โ””โ”€__MACOSX
    โ”‚  ._for_user
    โ”‚  
    โ””โ”€for_user
            ._Dockerfile
            ._flag
            ._libprob.so
            ._prob
๐Ÿ’ก ์ „์ฒด ๋กœ๋“œ๋งต
CykorCTF2025-asterisk ํ’€์ด ์ „์ฒด ๋กœ๋“œ๋งต
CykorCTF2025-asterisk ํ’€์ด ์ „์ฒด ๋กœ๋“œ๋งต

1. Premitive - Static Analysis

์‹œํ—˜๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ ๋„ˆ๋ฌด ์กธ๋ ค์„œ ์ ๋Š” ๋กธ์—…..
ํƒˆ๋ชจํƒˆ๋ชจ๋น”,, ๊ต์ˆ˜๋‹˜๊ป˜์„œ ๋‹ต์žฅ์ด ์˜ค์งˆ์•Š๋Š”๋‹ค

  1. ,,,
    ์ „์ฒด ํ•จ์ˆ˜ ๋ชฉ๋ก ํ™•์ธ: main, _start, _init, _fini ํ‘œ์ค€ ์ง„์ž…์ 
    ์ „์ฒด ํ•จ์ˆ˜ ๋ชฉ๋ก ํ™•์ธ: main, _start, _init, _fini ํ‘œ์ค€ ์ง„์ž…์ 
    main ํ•จ์ˆ˜ ํ™•์ธ: dlopen, dlsym, dlerror ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ
    main ํ•จ์ˆ˜ ํ™•์ธ: dlopen, dlsym, dlerror ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ
    • fopen, fread, fclose โ†’ ํŒŒ์ผ I/O
    • mmap, srand, rand -> ๋ฉ”๋ชจ๋ฆฌ/๋žœ๋ค ์œ„ ์‚ฌํ•ญ๋“ค์„ ๊ฐ„์ฃผ์–ด๋ดค์„ ๋•Œ, ์™ธ๋ถ€ .so ํŒŒ์ผ์„ ๋Ÿฐํƒ€์ž„์— ๋กœ๋“œํ•จ. ์ฆ‰, prob์€ ๋กœ๋”์ผ ๋ฟ ์‹ค์ œ ๋กœ์ง์€ libprob.so(์—์„œ ๋กœ๋“œํ•ด์˜ค๋Š” challenge_main)์— ์žˆ์Œ
    main ์„ธ๋ถ€ ์‚ฌํ•ญ
         // 1. ๋žœ๋ค ์‹œ๋“œ ์„ค์ • (urandom ๋˜๋Š” time)
         fopen("/dev/urandom", "r");
         srand(seed);
         // 2. ๋žœ๋ค ํŒจ๋”ฉ mmap (์ž์ฒด PIE ๊ตฌํ˜„)
         local_24 = (rand() & 0xff) << 0xc;  // 0 ~ 255 ํŽ˜์ด์ง€
         mmap(NULL, local_24, ...);
    
         // 3. libprob.so ๋กœ๋“œ
         dlopen("./libprob.so", RTLD_NOW);
    
         // 4. challenge_main ํ•จ์ˆ˜ ์ฐพ์•„์„œ ํ˜ธ์ถœ
         pcVar4 = dlsym(handle, "challenge_main");
         (*pcVar4)();  // challenge_main() ํ˜ธ์ถœ
    
  2. libprob.so์˜ challenge_main ๋ถ„์„
    libprob.so์˜ ํ•จ์ˆ˜ ๋ชฉ๋ก ํ™•์ธ
    libprob.so์˜ ํ•จ์ˆ˜ ๋ชฉ๋ก ํ™•์ธ
    readelf ๋ช…๋ น์–ด
    readelf ๋ช…๋ น์–ด
       //libpro.so์—์„œ custom๋œ ํ•จ์ˆ˜๋“ค์˜ ์˜คํ”„์…‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Œ.
       present @ 0x74c
       santa @ 0x7f5  
       rudolph @ 0x825
       elves @ 0x899
       challenge_main @ 0x8e1
       prologue @ 0x799
    
       void challenge_main(void)
    
       {
         undefined4 local_14 [2];
            
         setvbuf(stdin,(char *)0x0,2,0);
         setvbuf(stdout,(char *)0x0,2,0);
         do {
           prologue();
           __isoc99_scanf(&DAT_00010ae8,local_14);
           getchar();
           switch(local_14[0]) {
           case 1:
             santa();
             break;
           case 2:
             rudolph();
             break;
           case 3:
             elves();
             break;
           case 4:
             puts("Bye!");
                           /* WARNING: Subroutine does not return */
             exit(0);
           default:
             puts("Invalid choice!");
           }
         } while( true );
       }
    
    

    challenge_main์€ ๋‹จ์ˆœํžˆ ๋ฉ”๋‰ด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜

  3. challenge_main์˜ ๊ฐ ๋ฉ”๋‰ด๊ฐ€ ๋˜๋Š” ํ•จ์ˆ˜ ๋ถ„์„
     //1์ผ๋•Œ ํ˜ธ์ถœ๋˜๋Š” santa()
     void santa(void)
    
     {
       undefined1 auStack_c [4];
          
       printf("Index: ");
       __isoc99_scanf(&DAT_00010ac0,auStack_c);
       return;
     }
     //2์ผ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” roudolgh()
     void rudolph(void)
    
     {
       undefined4 local_18;
       int local_14 [2];
          
       printf("Index: ");
       __isoc99_scanf(&DAT_00010ac0,local_14);
       printf("Value: ");
       __isoc99_scanf(&DAT_00010acc,&local_18);
       *(undefined4 *)(&bss_buffer + local_14[0]) = local_18;
       puts("Written!");
       return;
     }
    
     //3์ผ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” elves()
     void elves(void)
    
     {
       char acStack_108 [255];
       undefined1 local_9;
          
       printf("Message: ");
       read(0,acStack_108,0xff);
       local_9 = 0;
       printf(acStack_108);
       putchar(10);
       return;
     }
    
     //4์ผ ๋•Œ๋Š” puts(Bye!)