Skip to content

Commit cb4991c

Browse files
authored
Fix regression in amd64.mov with 32-bit values >= 0x80000000 (#843)
Fixes #841 Caused by: #504 (9ca377c)
1 parent 323975f commit cb4991c

1 file changed

Lines changed: 31 additions & 15 deletions

File tree

  • pwnlib/shellcraft/templates/amd64

pwnlib/shellcraft/templates/amd64/mov.asm

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,26 @@ Example:
6161
mov rax, 0x1010110dfac01fe
6262
xor [rsp], rax
6363
pop rax
64-
>>> with context.local(os = 'linux'):
65-
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
66-
xor eax, eax /* (SYS_read) */
67-
>>> with context.local(os = 'freebsd'):
68-
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
69-
push (SYS_read) /* 3 */
70-
pop rax
71-
>>> with context.local(os = 'linux'):
72-
... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip()
73-
push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */
74-
pop rax
64+
>>> print shellcraft.amd64.mov('rax', 0xffffffff).rstrip()
65+
mov eax, 0xffffffff
66+
>>> print shellcraft.amd64.mov('rax', 0x7fffffff).rstrip()
67+
mov eax, 0x7fffffff
68+
>>> print shellcraft.amd64.mov('rax', 0x80010101).rstrip()
69+
mov eax, 0x80010101
70+
>>> print shellcraft.amd64.mov('rax', 0x80000000).rstrip()
71+
mov eax, 0x1010101 /* 2147483648 == 0x80000000 */
72+
xor eax, 0x81010101
73+
>>> with context.local(os = 'linux'):
74+
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
75+
xor eax, eax /* (SYS_read) */
76+
>>> with context.local(os = 'freebsd'):
77+
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
78+
push (SYS_read) /* 3 */
79+
pop rax
80+
>>> with context.local(os = 'linux'):
81+
... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip()
82+
push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */
83+
pop rax
7584

7685
Args:
7786
dest (str): The destination register.
@@ -99,25 +108,32 @@ if get_register(src):
99108
if dest.size == 64 and src.size <= 32:
100109
dest = get_register(dest.native32)
101110

102-
src_size = src.size
103111
else:
104112
with ctx.local(arch = 'amd64'):
105113
src = eval(src)
106114

107115
if not dest.fits(src):
108116
log.error("cannot mov %s, %r: dest is smaller than src" % (dest, src))
109117

110-
src_size = bits_required(src)
118+
orig_dest = dest
111119

112-
if dest.size == 64 and src_size <= 32:
120+
if dest.size == 64 and bits_required(src) <= 32:
113121
dest = get_register(dest.native32)
114122

115123
# Calculate the packed version
116124
srcp = packing.pack(src & ((1<<dest.size)-1), dest.size)
117125

118126
# Calculate the unsigned and signed versions
119127
srcu = packing.unpack(srcp, dest.size, sign=False)
120-
srcs = packing.unpack(srcp, dest.size, sign=True)
128+
129+
# N.B.: We may have downsized the register for e.g. mov('rax', 0xffffffff)
130+
# In this case, srcp is now a 4-byte packed value, which will expand
131+
# to "-1", which isn't correct.
132+
if orig_dest.size != dest.size:
133+
srcs = src
134+
else:
135+
srcs = packing.unpack(srcp, dest.size, sign=True)
136+
121137
%>\
122138
% if is_register(src):
123139
% if src == dest:

0 commit comments

Comments
 (0)