Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add new nop command features #967

Merged
merged 1 commit into from
Jul 21, 2023
Merged

add new nop command features #967

merged 1 commit into from
Jul 21, 2023

Conversation

therealdreg
Copy link
Collaborator

@therealdreg therealdreg commented Jul 20, 2023

Description/Motivation/Screenshots

The `nop` command allows you to easily patch instructions with nops.

nop [LOCATION] [--i ITEMS] [--f] [--n] [--b]


`LOCATION` address/symbol to patch (by default this command replaces whole instructions)

`--i ITEMS` number of items to insert (default 1)

`--f` Force patch even when the selected settings could overwrite partial instructions

`--n` Instead of replacing whole instructions, insert ITEMS nop instructions, no matter how many instructions it overwrites

`--b` Instead of replacing whole instructions, fill ITEMS bytes with nops

gef➤ 	nop
gef➤ 	nop $pc+3
gef➤ 	nop --i 2 $pc+3
gef➤ 	nop --b
gef➤ 	nop --b $pc+3
gef➤ 	nop --f --b --i 2 $pc+3
gef➤ 	nop --n --i 2 $pc+3

Against which architecture was this tested ?

"Tested" indicates that the PR works and the unit test (see docs/testing.md) run passes without issue.

  • x86-32
  • x86-64
  • ARM
  • AARCH64
  • MIPS
  • POWERPC
  • SPARC
  • RISC-V

Checklist

  • My PR was done against the dev branch, not main.
  • My code follows the code style of this project.
  • My change includes a change to the documentation, if required.
  • If my change adds new code, adequate tests have been added.
  • I have read and agree to the CONTRIBUTING document.

```

`LOCATION` address/symbol to patch
`LOCATION` address/symbol to patch (by default this command replace whole instruction(s))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`LOCATION` address/symbol to patch (by default this command replace whole instruction(s))
`LOCATION` address/symbol to patch (by default this command replaces whole instructions)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


`--f` Force patch when the final instruction/nop can be broken

`--n` Instead replace whole instruction(s), insert the number specified by ITEMS-value of nop(s)-instruction(s)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`--n` Instead replace whole instruction(s), insert the number specified by ITEMS-value of nop(s)-instruction(s)
`--n` Instead of replacing whole instructions, insert ITEMS nop instructions, no matter how many instructions it overwrites

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


`--n` Instead replace whole instruction(s), insert the number specified by ITEMS-value of nop(s)-instruction(s)

`--b` Instead replace whole instruction(s), fill with nop(s)-instruction(s) the number specified by ITEMS-value bytes
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`--b` Instead replace whole instruction(s), fill with nop(s)-instruction(s) the number specified by ITEMS-value bytes
`--b` Instead of replacing whole instructions, fill ITEMS bytes with nops

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

instructions/nops (full instruction size by default)
`--i ITEMS` number of items to insert (default 1)

`--f` Force patch when the final instruction/nop can be broken
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`--f` Force patch when the final instruction/nop can be broken
`--f` Force patch even when the selected settings could overwrite partial instructions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Outdated
"\n\tLOCATION\taddress/symbol to patch (by default this command replace whole instruction(s))"
"\t--i ITEMS\tnumber of items to insert (default 1)"
"\t--f\tForce patch when the final instruction/nop can be broken"
"\t--n\tInstead replace whole instruction(s), insert the number specified by ITEMS-value of nop(s)-instruction(s)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take from my suggestions above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Outdated
force_flag = args.f or False
fill_instructions = False if fill_nops or fill_bytes else True

if fill_nops + fill_bytes + fill_instructions != 1:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if fill_nops + fill_bytes + fill_instructions != 1:
if fill_nops and fill_bytes:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Show resolved Hide resolved
gef.py Outdated
if total_bytes % len(nop):
warn(f"Patching {total_bytes} bytes at {address:#x} will result in a partially patched instruction and may break disassembly")
if len(nop) > total_bytes or total_bytes % len(nop):
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-NOP (byte nr {total_bytes % len(nop):#x}) broken and may cause a crash or break disassembly")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please break up long lines

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Outdated
if len(nop) > total_bytes or total_bytes % len(nop):
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-NOP (byte nr {total_bytes % len(nop):#x}) broken and may cause a crash or break disassembly")
if not force_flag:
err("you must use --f to allow this kind of patch")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
err("you must use --f to allow this kind of patch")
err("Use --f (force) to ignore this warning")

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Outdated
final_ins_end_addr = curr_ins.address + curr_ins.size()

if final_ins_end_addr != target_end_address:
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-INSTRUCTION ({curr_ins.address:#x}) broken and may cause a crash or break disassembly")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-INSTRUCTION ({curr_ins.address:#x}) broken and may cause a crash or break disassembly")
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-INSTRUCTION ({curr_ins.address:#x}) being partial overwritten and may cause a crash or break disassembly")

and also wrap

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Owner

@hugsy hugsy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few things to changes (also from graz's review) then we're good

gef.py Show resolved Hide resolved
gef.py Outdated
if final_ins_end_addr != target_end_address:
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-INSTRUCTION ({curr_ins.address:#x}) broken and may cause a crash or break disassembly")
if not force_flag:
err("you must use --f to allow this kind of patch")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
err("you must use --f to allow this kind of patch")
err("You must use --f to allow misaligned patching.")

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

gef.py Outdated
err("you must use --f to allow this kind of patch")
return

nops = bytearray(nop * total_bytes) # this array will be bigger than needed when arch nop is > 1 but who cares
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is unhelpful, remove

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@therealdreg
Copy link
Collaborator Author

therealdreg commented Jul 21, 2023

btw, @hugsy suggests in discord join the "warning msg" + "use --f msg": done

Copy link
Owner

@hugsy hugsy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think examples in the docs need a bit more explanation in plain english.

docs/commands/nop.md Show resolved Hide resolved
@therealdreg therealdreg requested a review from hugsy July 21, 2023 06:42

`--n` Instead of replacing whole instructions, insert ITEMS nop instructions, no matter how many instructions it overwrites
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap to 100 according to editorconfig

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is?

docs/commands/nop.md Outdated Show resolved Hide resolved
docs/commands/nop.md Outdated Show resolved Hide resolved
gef➤ nop --f --b --i 2 $pc+3
```

Patching with 2 nops at $pc+3 address:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patch 2 nops at address $pc+3

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


def __init__(self) -> None:
super().__init__(complete=gdb.COMPLETE_LOCATION)
return

@only_if_gdb_running
@parse_arguments({"address": "$pc"}, {"--n": 0, "--b": False})
@parse_arguments({"address": "$pc"}, {"--i": 1, "--b": True, "--f": True, "--n": True})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but how can that work?

gef.py Show resolved Hide resolved
gef.py Show resolved Hide resolved
target_end_address = address + total_bytes
curr_ins = gef_current_instruction(address)
while curr_ins.address + curr_ins.size() < target_end_address:
if not Address(value=curr_ins.address + 1).valid:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the +1 is confusing. Why not but this check after curr_ins = get next so you don't need the +1?

isn't curr_ins.address already an Address? if so, if not curr_ins.valid

Copy link
Collaborator Author

@therealdreg therealdreg Jul 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I dont want disasm invalid Address (avoid exception / error .. etc) I think the current code is OK and more secure

gef.py Show resolved Hide resolved
gef.py Outdated Show resolved Hide resolved
@therealdreg therealdreg changed the title new nop command features add new nop command features Jul 21, 2023
@therealdreg
Copy link
Collaborator Author

added a test to check if --b and --n at same time == error

if final_ins_end_addr != target_end_address:
warn(f"Patching {total_bytes} bytes at {address:#x} will result in LAST-INSTRUCTION "
f"({curr_ins.address:#x}) being partial overwritten and may cause a crash or "
f"break disassembly. You must use --f to allow misaligned patching.")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
f"break disassembly. You must use --f to allow misaligned patching.")
"break disassembly. You must use --f to allow misaligned patching.")

@hugsy hugsy merged commit 99c59a9 into hugsy:dev Jul 21, 2023
3 checks passed
@hugsy hugsy added this to the Release: next milestone Jul 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants