Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions winpwn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .context import context
from .winpwn import process,remote
from .dbg import gdb,windbg,x64dbg,windbgx,init_debugger
from .misc import p8,p16,p32,p64,u8,u16,u32,u64,pause,sleep,NOPIE,PIE,Latin1_encode,Latin1_decode,color,hexdump
from .misc import p8,p16,p32,p64,u8,u16,u32,u64,pause,sleep,NOPIE,PIE,Latin1_encode,Latin1_decode,color,hexdump,cyclic,cyclic_find
from .asm import asm,disasm
from .winfile import winfile
from .wincs import wincs
Expand All @@ -21,7 +21,7 @@
__all__=[
'process','remote','gdb','windbg','x64dbg','windbgx',
'context',
'p8','p16','p32','p64','u8','u16','u32','u64',
'p8','p16','p32','p64','u8','u16','u32','u64',"cyclic","cyclic_find"
'pause','sleep','hexdump','color',"NOPIE","PIE",
"tostr",'tobyte',
"asm","disasm",
Expand Down
51 changes: 50 additions & 1 deletion winpwn/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,53 @@ def showbuf(buf,is_noout=None):
if buf.endswith(context.newline):
os.write(sys.stdout.fileno(), Latin1_encode(buf))
else:
os.write(sys.stdout.fileno(), Latin1_encode(buf+'\n'))
os.write(sys.stdout.fileno(), Latin1_encode(buf+'\n'))

def cyclic(length=None):
"""
Generate a cyclic pattern of 4‑byte tokens from aaaa to zzzz.
If length is given, return only the first `length` bytes.
"""
alphabet = b'abcdefghijklmnopqrstuvwxyz'
pattern = b''
for a in alphabet:
for b in alphabet:
for c in alphabet:
for d in alphabet:
pattern += bytes([a, b, c, d])
if length is not None and len(pattern) >= length:
return pattern[:length]
return pattern

def cyclic_find(subseq):
"""
Return the byte offset of a 4‑byte token in the cyclic pattern.
subseq can be:
- a 4‑character string (e.g., "aaad")
- an integer (e.g., 0x64616161, which is little‑endian for "aaad")
Returns -1 if the token is invalid (not in the pattern).
"""
# Convert integer to little‑endian 4‑byte string
if isinstance(subseq, int):
# Mask to 32 bits and pack as little‑endian
subseq = struct.pack('<I', subseq & 0xFFFFFFFF)
if isinstance(subseq, bytes):
# Decode to Latin1 string
subseq = Latin1_decode(subseq)
# Now subseq is a str of length 4
if len(subseq) != 4:
raise ValueError("cyclic_find: substring must be exactly 4 characters")
# Convert each character to its index (a=0, b=1, ..., z=25)
indices = []
for ch in subseq:
if 'a' <= ch <= 'z':
indices.append(ord(ch) - ord('a'))
else:
return -1 # character not in alphabet
# Compute position in the 4‑character token sequence
pos = (indices[0] * 26**3 +
indices[1] * 26**2 +
indices[2] * 26 +
indices[3])
# Each token occupies 4 bytes
return pos * 4