Skip to content

Instantly share code, notes, and snippets.

@alexander-hanel
Last active January 16, 2024 08:02
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alexander-hanel/faff87d25f4b2896241c8f835fa1a321 to your computer and use it in GitHub Desktop.
Save alexander-hanel/faff87d25f4b2896241c8f835fa1a321 to your computer and use it in GitHub Desktop.
IDAPYTHON script for patching bytes that match a regex pattern with NOPs.
import idautils
import re
import struct
"""
Example 1
.text:3500108D 60 pusha
.text:3500108E 66 B8 65 4B mov ax, 4B65h
.text:35001092
.text:35001092 loc_35001092: ; CODE XREF: .text:35001099↓j
.text:35001092 66 BB 66 4B mov bx, 4B66h
.text:35001096 66 39 D8 cmp ax, bx
.text:35001099 75 F9 jnz short near ptr loc_35001092+2
.text:3500109B 61 popa
"""
NOP_ME_PATTERN = [b"\x60.{1,20}\x75.{0,20}\x61", b"\x60.{0,20}\xE8\x00\x00\x00\x00.{0,20}\xC3\x61", b"\x60.{0,20}\x75.{0,20}\x61" ]
class MemHelper:
def __init__(self):
self.mem_results = b""
self.mem_offsets = []
if not self.mem_results:
self._get_memory()
def _get_memory(self):
result = b""
segments_starts = [ea for ea in idautils.Segments()]
offsets = []
start_len = 0
for start in segments_starts:
end = idc.get_segm_end(start)
result += idc.get_bytes(start, end - start)
offsets.append((start, start_len, len(result)))
start_len = len(result)
self.mem_results = result
self.mem_offsets = offsets
def to_virtual_address(self, offset):
va_offset = 0
for seg in self.mem_offsets:
if seg[1] <= offset < seg[2]:
va_offset = seg[0] + (offset - seg[1])
return va_offset
mem = MemHelper()
for mm in NOP_ME_PATTERN:
match = re.finditer(mm, mem.mem_results, re.DOTALL)
if match:
for m in match:
length = m.end() - m.start()
offset = mem.to_virtual_address(m.start())
if idc.get_segm_name(offset) == '.text':
flags = idc.get_func_attr(offset,FUNCATTR_FLAGS)
if flags != idc.BADADDR:
if flags & FUNC_LIB or flags & FUNC_THUNK:
continue
print(hex(offset))
nop = b"\x90" * length
ida_bytes.patch_bytes(offset, nop)
@alexander-hanel
Copy link
Author

Fixed Non-IDA Version

import re
import pefile
import sys
import traceback
import hexdump

"""
Example 1

.text:3500108D 60                              pusha
.text:3500108E 66 B8 65 4B                     mov     ax, 4B65h
.text:35001092
.text:35001092                         loc_35001092:                           ; CODE XREF: .text:35001099
.text:35001092 66 BB 66 4B                     mov     bx, 4B66h
.text:35001096 66 39 D8                        cmp     ax, bx
.text:35001099 75 F9                           jnz     short near ptr loc_35001092+2
.text:3500109B 61                              popa

"""

NOP_ME_PATTERN = [  
                    b"\x60.{0,20}\x75.{0,20}\x61", 
                    b"\x60.{0,20}\xE8\x00\x00\x00\x00.{0,20}\xC3\x61", 
                    b"\x60.{0,20}[\x74|\x75].{0,20}\x61" 
                ]


try:
    pe = pefile.PE(sys.argv[1])
    for section in pe.sections:
        if b".text" in section.Name:
            text_data = section.get_data()
            temp_data = list(text_data)
            section_offset = section.PointerToRawData
            for mm in NOP_ME_PATTERN:
                match = re.finditer(mm, text_data, re.DOTALL)
                if match:
                    for m in match:
                        length = m.end() - m.start()
                        for i in range(0, length):
                            temp_data[m.start()+i] = 0x90
            test = bytes(temp_data)
            pe.set_bytes_at_offset(section_offset, bytes(temp_data))
    pe.write(filename="newfile.exe")
except Exception as e:
    print(e)
    traceback.print_exc(file=sys.stdout)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment