# checksec
# process
IDA에서 ctrl + u 를 누르면 String Window로 갈 수 있다.
바이너리를 넣었을 때 Flag와 Top secret 파일이 같이 생겨서 String Window를 봤다.
그럼 Statically linked binary에서 main함수를 더 빨리 찾을 수 있을 것이다.
바이너리를 실행시켰을 때 Input name이 출력됐으므로 Input name을 따라가면 main함수를 찾을 수 있을 것이다.
전역변수 unk_6CCD60에 입력받는다.
scanf면 길이제한은 없다. (다만 뒤에 null byte가 같이 붙음)
return address를 덮을 수 있다.
TOP_SECRET을 따라가보면 이것도 MAIN함수에서 사용되는데, INPUT NAME 출력위한 함수 호출 전에 EDI 레지스터에 TOP_SECRET 인자를 넣고 SUB_43F670 함수를 호출한다.
입력은 UNK_6CCD60에 받는다.
어셈블리어로 확인해보면 read 호출 전에 0x12c인자를 호출하는데 이게 입력받는 크기이다.
fp = fopen(“top_secret”, “r”) : top_secret 파일을 열어서 파일 포인터를 전역변수 fp로 설정한다.
read(fp, unk_6ccd6a, 0x12c) : 전역변수 unk_6ccd6a에 fp를 이용해서 0x12c만큼 적는다.
write(1, unk_6ccd6a, read에서 입력받은 바이트) : read에서 입력받은 것 출력
flag파일을 열어주는 함수도 있다.
flag파일을 열 수 있도록 하면 될 것 같다.
fd 값은 호출되는 순서로 값이 정해진다.
따라서 write에서 이 fd 값에 따라 해당 번호의 것을 가져와주므로 flag 파일에 대한 순서를 알면 된다.
파일 디스크립터(fd)는 stdin이 0, stdout이 1, stderr가 2인 정수로 정해져있고 그 다음은 열려있는 파일을 참조하기 위한 것이다.
따라서 shell은 보통 3가지 파일 디스크립터가 항상 열려있고 (미리 할당되어있고)
보통 open()을 하게 되면 fd 값은 3이 된다.
즉, 가장 먼저 open()한 파일에 대한 디스크립터 값이 3이 된다는 것이다.
flag함수를 따라가보면 flag함수가 init함수에서 xreference를 두고있다.
Start 함수가 __libc_start_main을 할 때 main함수보다 init함수를 먼저 호출하므로 init함수에 xreferemce를 두는 flag함수는 main의 누구보다 먼저 open됨을 알 수 있다.
따라서 flag파일에 대한 fd값이 3이 된다.
fp 전역변수 값을 3으로 변조하면 write 시 flag파일에 대한 파일 디스크립터에 해당하게 write되므로 flag가 출력될 수 있다.
scanf함수에서 전역변수에 입력해서 BOF가 일어나므로 여기서 0x138의 offset을 준 후 fp 값을 p8(3)을 덮으면 flag가 출력된다.
# exploit code
#!/usr/bin/python
from pwn import *
context.log_level = 'debug'
p = process("./j0n9hyun_secret")
p = remote("ctf.j0n9hyun.xyz", 3031)
p.sendlineafter("input name: ", 'A'*0x138 + p8(3))
p.interactive()
# exploit
[HackCTF] Unexploitable #3 (0) | 2020.04.20 |
---|---|
[HackCTF] babyfsb (0) | 2020.03.25 |
[HackCTF] Welcome_REV (Reversing) (0) | 2020.03.09 |
[HackCTF] World best encryption tool (0) | 2020.03.09 |
[HackCTF] babyheap (0) | 2020.03.09 |