avatar

5.12日笔记 (week 4)

昨天看雪的题太恶心了!实在是做不动了!我是废物!😡 呜呜呜 😭 今天学习angr!奥里给😀

angr

步入正题!科二师傅给我发了挺多的资料,我准备今天都学一下

大概angr有一个标准的模板,sim.explore最多接受两个参数。

find可以是一个地址,也可以是一个bool函数

avoid可以是一个地址,可以是一个地址列表,也可以是一个bool函数

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
import angr
import sys

def main(argv):
bin_path = argv[1]
p = angr.Project(bin_path)
init_state = p.factory.entry_state()
sim = p.factory.simulation_manager(init_state)

def is_good(state):
return b'Good Job' in state.posix.dumps(1)

def is_bad(state):
return b'Try_again' in state.posix.dumps(1)

sim.explore(find = is_good ,avoid = is_bad)

if sim.found:
found_state = sim.found[0]
print("Flag: {}".format(found_state.posix.dumps(0)))
else :
print("cannot found a solution")

if __name__ == "__main__":
main(sys.argv)

大部分的资料在 网址: angr.io

小黄书更新:

除法优化

上次除法优化搞了搞,vct师傅给我发了他的除法优化的笔记,直接就他看的了,写的很好

先给一些背景:

(1)比如 7 / 2 = 3 …… 1 -7 / 2 = -3 …… -1

比较重要的是,余数的绝对值小于除数的绝对值,并且余数和被除数同正负

(2)由于C语言中除法是向0取整,也就是“截断除法”

不难发现,正数除以正数时,截断除法相当于向下取整(3.5 -> 3);而负数除以正数时,截断除法相当于向上取整( -3.5 -> -3 )

(3)除以2的k次幂通常会被优化成右移k位,这里考虑除以2时

用一个signed byte表示7,是00000111,右移一位变成00000011是3,是正确的

但是,考虑-7/2,-7是11111001,右移一位后变成11111100,这是-4,因为这是向下取整的结果,所以比正确的答案 -3少了1

代码中为了统一和效率,如果是32位的数字,会先右移31位扩展符号位。原先是正数则最高位是0,那么最后会变成32个0,也就是0,;原先是负数最高位是1,最后会变成32个1,也就是-1,暂且把这个扩展符号位后形成的数记作S,

那么,我们只需要把右移一位的结果,减去这个S,就可以得到正确的截断除法的值

7/2 = 7>>1 – (0) = 3 -7/2 == -7>>1 – (-1) = -3

( 这一点在例题代码中会再次提到 )

(4)当除以正数N,而N不是2的次幂时,编译器会生成一个magic_number(C),以使除法优化成乘法,提高效率

image-20200512180523744

手动的推导过程,图片中的证明表示:被除数(正数)乘以magic_number后再右移n位,即为除法的结果;如果是负数需要 +1,最后统一减去符号扩展形成的数即可,也就是高位存放符号位的地方

https://ctftime.org/task/5294?tdsourcetag=s_pcqq_aiomsg

image-20200512181826245

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cat foo.c
long long div(long long x) {
return x / N;
}
$ gcc -DN=$N -c -O2 foo.c
$ objdump -d foo.o

foo.o: file format elf64-x86-64


Disassembly of section .text:

0000000000000000
:
0: 48 89 f8 mov %rdi,%rax
3: 48 ba 01 0d 1a 82 9a movabs $0x49ea309a821a0d01,%rdx
a: 30 ea 49
d: 48 c1 ff 3f sar $0x3f,%rdi
11: 48 f7 ea imul %rdx
14: 48 c1 fa 30 sar $0x30,%rdx
18: 48 89 d0 mov %rdx,%rax
1b: 48 29 f8 sub %rdi,%rax
1e: c3 retq
$ echo “HarekazeCTF{$N}” > /dev/null

手算吧!

0x49ea309a821a0d01为magic number给了rdx,我们右移了63位也就是剩余的符号位是给了rdi,如果是正数那么就是0,负数就是-1,imul扩展了乘积高位被放在rdx,低位被放在rax

这么看,因为rdx扩展了,大概就是已经移动64位,然后再移动了48位也就是112位,那么计算就是0x49ea309a821a0d01,n=112

公式就是 c = 2^n / y y是除数,那么y = 2^n / c

image-20200512194355299

974873638438446

算术结果溢出

假设如果我们占据4字节32位内存空间数据进行运算,得到的结果超过了存储空间大小,就会产生溢出

int型数据0xFFFFFFFF加2就会得到超出int类型的存储范围,超出的部分就叫溢出数据,溢出的数据不能保存,会丢失,有符号数来说,原数据是负数,溢出后表示符号的最高位被进位,原来的1变成0,那么负数也被变成了正数0

image-20200512210122860

一个无符号数产生溢出后会从一个最大数变成最小数,有符号数溢出会修改符号位

1
2
3
4
//利用溢出跳出循环
for(int i = 1 ; i > 0 ; i++){
printf("%d\r\n",i)
}

int的类型i是一个有符号数,当i等于它允许取到的最大整数值0x7FFFFFFF时,再加上1,数值会产生进位,将符号位0修改为1,最终结果为0x80000000,这时候最高位为1,有符号来说是一个负数,也就是最大的负数,for直接跳出循环

Flare-on6 demo

拿到题以后发现是一个属于3d的一个模型image-20200513012556563

我们直接去看一下这个东西,放到ida

image-20200513012651687

发现什么都没有,我认为是PE结构出了问题,可能是代码段和数据段?还有PE载入点的问题吧,去用CFF看看

image-20200513012822792

发现什么段都没有,我准备用winhex看一下

image-20200513012939099

发现了一个问题就是说,在我自己学习PE结构的时候,应该会有一个对其的原则来用00填充,类似于书的最后一页可以是一个字,但是不能去裁剪的原理差不多,我发现整个pe结构根本没有00填充对齐的原则

借鉴了国外一个大佬这个题的wp的PE解释很好:https://www.bigmessowires.com/2015/10/08/a-handmade-executable-file/

https://github.com/GameHackingBook/GameHackingCode/blob/master/Chapter8_Direct3DApplication/main.cpp

第一次遇见了 x,y,z的问题,根据3D的规则,直接学习了一波用xdbg看一下

后面段看了大佬博客复现了:https://bruce30262.github.io/flare-on-challenge-2019-write-up/#level-5

没啥心情做了,👴佛了,网鼎的事情真的,不说什么了,有什么事情直接找我对线吧,👴跟P3打游戏去!

Author: L0x1c
Link: https://l0x1c.github.io/2020/05/12/2020-5-12/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶