Command reference
Every command Picklock accepts, with the arguments its parser declares. This
page is generated from the code, so it cannot drift from what help prints at
the prompt.
Commands are named namespace:command. Typing a namespace on its own
(scan) prints that namespace’s page; help <command> prints one command’s
arguments; and every command also answers to --help.
Process
Find a target process, attach to it, and see what it is.
picklock> ps:list chrome
+-------+------------+
| PID | NAME |
+-------+------------+
| 41902 | chrome.exe |
+-------+------------+
1 row in set (0.01 sec)
ps:close
Detach from the current process.
ps:close
Takes no arguments.
Closes the OS handle and drops the scan results, the pointer paths and the cached memory map. The target itself is untouched — nothing Picklock wrote to it is undone.
ps:info
Describe the attached process in detail.
ps:info
Takes no arguments.
Enumerates the memory map to report how much of the address space is mapped, so it is the slower of the two ways to look at a target.
ps:list
List the processes visible to you.
ps:list [pattern] [--pid-sort] [--case-sensitive] [--limit N] [--page N] [--all]
[pattern]keep processes whose name contains this text; an all-digit pattern also matches that PID exactly
--pid-sortsort by PID instead of by name
--case-sensitivematch the pattern case-sensitively
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
Only processes your user can see are listed. Run Picklock elevated to see (and open) processes belonging to other users.
Examples
ps:list
ps:list chrome
ps:list --pid-sort --limit 50
ps:open
Attach to a process by PID or name.
ps:open [pid|name] [--pid PID] [--name NAME] [--ignore-case] [--case-sensitive] [--partial] [--strict-bitness]
[pid|name]the PID (all digits) or the process name to attach to
--pid PIDattach by PID, when the target could be read either way
--name NAMEattach by process name, when the name is all digits
-i, --ignore-casematch the name regardless of case
--case-sensitivematch the name case-sensitively (the default on Linux and macOS)
--partialmatch the name as a substring (‘chrome’ finds ‘chrome.exe’); fails when more than one process matches, listing the candidates
--strict-bitnessrefuse to attach when the target’s 32/64-bit width cannot be determined, instead of guessing it from this interpreter
An all-digits target is taken as a PID, anything else as a process name; force either reading with –pid or –name.
–strict-bitness is worth using before a pointer scan, where a wrong pointer width is silent rather than loud.
Attaching replaces any previous target and clears the scan results.
Examples
ps:open 4242
ps:open notepad.exe
ps:open chrome --partial -i
ps:threads
List the target’s threads.
ps:threads [--limit N] [--page N] [--all]
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
STATE and PRIORITY are filled in only where the platform exposes them cheaply (Linux does; Windows and macOS leave them empty).
What a TID is differs by platform, and only two of the three are a property of the thread itself:
Linux the POSIX task id — the same number everything else reports
Windows the kernel thread id — likewise
macOS a Mach port name, which means something only to the process that asked
That last one is the trap: on macOS two tools looking at the same process get different numbers for the same threads, and neither is wrong. It is a handle, not a name — do not carry it between tools, and do not expect it to match Activity Monitor.
Memory
Read, write and inspect the target’s memory.
picklock> memory:read game.exe+0x1234 int32
+--------------------+-------+-------+
| ADDRESS | TYPE | VALUE |
+--------------------+-------+-------+
| 0x00007FF6A41B1234 | int32 | 100 |
+--------------------+-------+-------+
1 row in set (0.00 sec)
memory:alloc
Allocate memory inside the target.
memory:alloc <size> [--permission N]
sizenumber of bytes to allocate; hex accepted (e.g. 0x1000)
--permission Nplatform-specific protection: a PAGE_* value on Windows (default PAGE_EXECUTE_READWRITE), a VM_PROT_* bitmask on macOS
Reserves and commits SIZE bytes in the target’s address space and prints the base address. The region stays until ‘memory:free’ releases it.
Not available on Linux, which has no cross-process allocation syscall.
Examples
memory:alloc 4096
memory:alloc 0x1000
memory:free
Release memory allocated with ‘memory:alloc’.
memory:free <address> [size]
addressbase address returned by ‘memory:alloc’
[size]region size; only needed to free a region this session did not allocate, since PyMemoryEditor remembers its own
Not available on Linux, for the same reason as ‘memory:alloc’.
Examples
memory:free 0x7ffee3a01000
memory:free 0x7ffee3a01000 4096
memory:hex
Show a range of memory as hex and text.
memory:hex <address> [length] [--width N] [--watch] [--interval S]
addressaddress expression: a literal, module+offset, [pointer] or #N — see ‘help address’
[length]number of bytes to read (default 256); hex accepted
--width Nbytes per line, overriding the ‘hex_width’ setting
-w, --watchredraw as the bytes change, until ENTER
--interval Sseconds between redraws with –watch, overriding ‘watch_interval’
The classic three-column layout: absolute address, hex bytes, printable ASCII. Length defaults to 256 bytes.
With –watch it redraws in place until you press ENTER, which turns it into a live view of a structure — a whole record changing at once, where ‘memory:watch’ follows a single value.
The read is a single call, so a range that crosses into an unmapped page fails as a whole rather than returning half the bytes.
Examples
memory:hex 0x7ffee3a01000
memory:hex game.exe+0x1000 512
memory:hex #1 64 --width 8
memory:hex #1 64 --watch
memory:modules
List the modules loaded in the target.
memory:modules [pattern] [--limit N] [--page N] [--all]
[pattern]keep modules whose name or path contains this text
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
A module is the main executable or a shared library (.dll / .so / .dylib). Its BASE moves on every launch under ASLR, which is why an address is best written as ‘module+offset’ — see ‘help address’.
Running this command refreshes the module table the address parser uses, so run it after the target loads a library.
Examples
memory:modules
memory:modules libc
memory:read
Read a typed value from an address.
memory:read <address> [type] [length] [--count N] [--hex]
addressaddress expression: a literal, module+offset, [pointer] or #N — see ‘help address’
[type]value type; defaults to int32 (see ‘help types’)
[length]byte width, required for the ‘string’ and ‘bytes’ types
--count Nread N consecutive values, stepping by the type’s width
--hexprint integers in hexadecimal
The type defaults to int32 — except for a ‘#N’ row, which is read the way the scan that found it read it. A byte the scan matched should not come back as a four-byte number.
‘string’ and ‘bytes’ need a length in bytes; the fixed-width types ignore one.
The address is an expression — see ‘help address’ — so a pointer chain can be read in one go.
Examples
memory:read 0x7ffee3a01000
memory:read game.exe+0x1234 int32
memory:read [game.exe+0x1a2b3c]+0x18 float
memory:read 0x7ffee3a01000 string 32
memory:read #1 int32 --count 8
memory:regions
List the target’s mapped memory regions.
memory:regions [--writable] [--executable] [--shared] [--path TEXT] [--at ADDRESS] [--limit N] [--page N] [--all]
--writablekeep only writable regions
--executablekeep only executable regions
--sharedkeep only shared or file-backed mappings
--path TEXTkeep regions whose backing file path contains TEXT
--at ADDRESSshow only the region containing this address
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
The memory map is re-read on every call, so it reflects allocations the target made since the last look.
The PERMS column reads like /proc/
Examples
memory:regions --writable
memory:regions --at 0x7ffee3a01000
memory:regions --path libc
memory:watch
Poll an address and print it as it changes.
memory:watch <address> [type] [length] [--interval S] [--count N] [--all]
addressaddress expression: a literal, module+offset, [pointer] or #N — see ‘help address’
[type]value type; defaults to int32 (see ‘help types’)
[length]byte width, required for the ‘string’ and ‘bytes’ types
--interval Sseconds between reads, overriding the ‘watch_interval’ setting
--count Nstop after N samples; without it, watch runs until you press ENTER
-a, --allprint every sample, not only the ones whose value changed
Reads the address on a timer and prints a line per sample. Press ENTER to stop; Ctrl+C is left to mean what it means everywhere else, which is leaving the shell.
By default only samples whose value differs from the previous one are printed, which turns the terminal into a change log — so a value that is not moving shows one line and then nothing, and ‘–all’ is how you tell that apart from a watch that has stopped.
A ‘#N’ row is watched with the type the scan used, not int32.
This is the terminal answer to a cheat table: leave it running in one window while the target does its thing.
Examples
memory:watch game.exe+0x1234 int32
memory:watch [base+0x10]+0x8 float --interval 0.1
memory:watch #1 int32 --count 20 --all
memory:write
Write a typed value to an address.
memory:write <address> <type> <value> [--length N] [--null-terminated]
addressaddress expression: a literal, module+offset, [pointer] or #N — see ‘help address’
typevalue type (see ‘help types’)
valuethe value to write, parsed according to the type: integers accept 0x/0o/0b prefixes, booleans accept true/false/on/off, ‘bytes’ takes hex (‘DE AD BE EF’) and ‘string’ takes the text verbatim
--length Nbuffer width for string/bytes; defaults to the natural width of the value given
--null-terminatedappend a NUL after a string, for C-string writes
There is no confirmation and no undo. Writing into a live process can crash it — read the address first if you are not sure of it.
Examples
memory:write 0x7ffee3a01000 int32 100
memory:write game.exe+0x1234 float 99.5
memory:write #2 bytes 'DE AD BE EF'
memory:write 0x7ffee3a01000 string Picklock --null-terminated
Scanning
Search memory for a value, then narrow what you found.
picklock> scan:value int32 100 --writable
Showing 20 of 3184 rows — writable regions only (1.42 sec)
picklock> scan:next 95
+-----+--------------------+-------+
| ROW | ADDRESS | VALUE |
+-----+--------------------+-------+
| #1 | 0x00000201A4C0F118 | 95 |
+-----+--------------------+-------+
1 row in set (0.02 sec)
scan:aob
Scan for a byte pattern with wildcards (AOB).
scan:aob <pattern> [--max N]
patternIDA-style signature: hex bytes separated by spaces, with ‘?’ or ‘??’ for any single byte. Quote it, since it contains spaces
--max Nstop after N hits, overriding the ‘max_results’ setting
This is how you find code that moves between builds: the opcodes stay put while the operands change, so you wildcard the operands. The result set holds the address of each match and can be refined with ‘scan:next’ or read with ‘memory:read #1’.
Examples
scan:aob "48 8B ? ? 00 00"
scan:aob "DE AD BE EF"
scan:drop
Remove the named result rows.
scan:drop <row> [row ...]
row [row ...]row numbers from ‘results’, singly or as ranges: 1 4 7-9 (a ‘#’ prefix is optional)
The inverse of ‘keep’. Ranges work the same way.
Examples
scan:drop 2
scan:drop 5-12
scan:keep
Keep only the named result rows.
scan:keep <row> [row ...]
row [row ...]row numbers from ‘results’, singly or as ranges: 1 4 7-9 (a ‘#’ prefix is optional)
Use it when you can see which candidates are real and would rather not invent a comparison that happens to exclude the others.
Examples
scan:keep 1
scan:keep 1 3 7-9
scan:next
Narrow the results with another comparison.
scan:next [value] [--eq VALUE] [--ne VALUE] [--gt VALUE] [--lt VALUE] [--ge VALUE] [--le VALUE] [--between A B] [--not-between A B] [--changed] [--unchanged] [--increased] [--decreased] [--increased-by VALUE] [--decreased-by VALUE]
[value]the value to keep; the same as –eq VALUE
--eq VALUEkeep values equal to VALUE — the same as giving VALUE on its own
--ne VALUEkeep values different from VALUE
--gt VALUEkeep values greater than VALUE
--lt VALUEkeep values smaller than VALUE
--ge VALUEkeep values greater than or equal to VALUE
--le VALUEkeep values smaller than or equal to VALUE
--between A Bkeep values inside the range A…B, inclusive
--not-between A Bkeep values outside the range A…B
--changedkeep addresses whose value differs from the last reading
--unchangedkeep addresses whose value equals the last reading
--increasedkeep addresses whose value grew since the last reading
--decreasedkeep addresses whose value shrank since the last reading
--increased-by VALUEkeep addresses that grew by exactly VALUE
--decreased-by VALUEkeep addresses that shrank by exactly VALUE
Re-reads every address in the result set and keeps the ones that still match. A bare value means equality: ‘scan:next 95’ keeps the addresses now holding 95.
The comparisons that need no value of their own are for when you cannot see it — a health bar with no number. They measure each address against what the last scan read there, so making the value move in the target and then asking for ‘–decreased’ narrows the set without you ever knowing the number.
Addresses that have become unreadable (the target freed them) are dropped.
Examples
scan:next 95
scan:next --changed
scan:next --decreased
scan:next --gt 50
scan:next --between 10 20
scan:regex
Scan for text matching a regular expression.
scan:regex <pattern> [--length N] [--max N]
patterna regular expression, UTF-8 encoded and matched against raw memory
--length Nthe widest match to expect, in bytes (default 64); also how many bytes are read back for the VALUE column
--max Nstop after N hits, overriding the ‘max_results’ setting
Because the match runs over bytes, a metacharacter spans one byte: ‘.’ matches any single byte and ‘\d’ is ASCII-only, so quantify with care around non-ASCII text.
A regex has no fixed width, which is why –length matters: it is what lets a match straddling an internal chunk boundary still be found.
Examples
scan:regex "Player[0-9]+"
scan:regex "https?://[a-z.]+" --length 128
scan:reset
Discard the current scan results.
scan:reset
Takes no arguments.
Clears the result set so the next ‘scan’ starts a fresh cycle. The attached process is left alone.
scan:results
Show the current result set, re-read.
scan:results [--export FILE] [--limit N] [--page N] [--all]
--export FILEwrite every result to a JSON file instead of paging through them
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
Reads every address again, so the VALUE column is what the target holds now, not what it held when the scan ran. The PREVIOUS column shows the value the last scan recorded — the one ‘scan:next changed’ and friends compare against — and is filled in only where the two differ.
Row numbers are what ‘#N’ refers to in an address, and they keep counting across pages: row #21 is the first on page 2 of twenty.
–export writes every result to a JSON file — all of them, not the page on screen — with the scan’s type and width alongside, so the file says what its numbers mean.
Examples
scan:results
scan:results --all
scan:results --page 3 --limit 10
scan:results --export found.json
scan:value
Search the whole address space for a value.
scan:value <type> [value] [--eq VALUE] [--ne VALUE] [--gt VALUE] [--lt VALUE] [--ge VALUE] [--le VALUE] [--between A B] [--not-between A B] [--writable] [--all-regions] [--length N] [--max N]
typevalue type to search for (see ‘help types’)
[value]the value to search for; the same as –eq VALUE
--eq VALUEkeep values equal to VALUE — the same as giving VALUE on its own
--ne VALUEkeep values different from VALUE
--gt VALUEkeep values greater than VALUE
--lt VALUEkeep values smaller than VALUE
--ge VALUEkeep values greater than or equal to VALUE
--le VALUEkeep values smaller than or equal to VALUE
--between A Bkeep values inside the range A…B, inclusive
--not-between A Bkeep values outside the range A…B
--writablescan only writable regions — much faster, and where a changing value almost always lives
--all-regionsscan everything, overriding the ‘writable_only’ setting
--length Nbuffer width for string/bytes scans
--max Nstop after N hits, overriding the ‘max_results’ setting
The first scan of a cycle. Every matching address is kept as the result set that ‘scan:next’, ‘scan:results’ and the ‘#N’ address form work on.
A bare value means equality, which is what a scan almost always is; every other comparison is named by its flag, so the value slot only ever holds a value.
Ctrl+C stops a scan and keeps what it had already found.
Examples
scan:value int32 100
scan:value float 99.5 --writable
scan:value int32 --between 100 200
scan:value string Picklock
scan:value int32 --gt 1000
Aliases
Give a command a shorter name of your own.
picklock> alias:add r memory:read
r = memory:read
picklock> alias:add find-text scan:value string
find-text = scan:value string
picklock> find-text Picklock
(runs 'scan:value string Picklock')
alias:add
Give a command a shorter name.
alias:add <name> <command> [command ...]
namethe word you want to type
command [command ...]the command it stands for, and any arguments that always go with it
The alias replaces the first word of a line, and anything else you type follows what it stands for — so with ‘find-text’ set to ‘scan:value string’, typing ‘find-text Picklock’ runs ‘scan:value string Picklock’.
A name already taken by a command or another alias is refused rather than shadowing it, and the command an alias points at has to exist, so a typo is caught here rather than the next time you use it.
Aliases are remembered between runs — they are the one thing Picklock stores on disk. ‘alias:list’ says where.
Examples
alias:add r memory:read
alias:add find-text scan:value string
alias:add w memory:write
alias:list
Show the aliases defined in this session.
alias:list
Takes no arguments.
Only the ones you have added. The shell’s own shortcuts — ‘quit’, ‘cls’, ‘\h’, ‘.’ — are part of the commands themselves and are listed with them, in ‘help
They are stored in a file, whose path is printed under the table. Setting PICKLOCK_CONFIG_DIR moves it — useful for keeping a throwaway set apart from the one you rely on.
alias:remove
Forget an alias.
alias:remove <name>
namethe alias to forget
Only aliases you added can be removed; the shell’s own shortcuts are part of their commands.
Examples
alias:remove r
Configuration
Show or change how Picklock behaves.
picklock> config:set writable_only on
writable_only = on
picklock> config:list
+---------+-------+------------------------------------+
| SETTING | VALUE | DESCRIPTION |
+---------+-------+------------------------------------+
| limit | 20 | Rows printed per result table ... |
+---------+-------+------------------------------------+
config:list
Show the settings and their current values.
config:list
Takes no arguments — the whole table, every time. There are eight of them and they fit on a screen, so picking one out would be a filter for a list that does not need filtering.
A change is remembered between runs, so the shell comes back the way you left it. Only what you changed is stored, so a default that moves in a later release still reaches you — and ‘config:reset’ puts one back, which restarting no longer does.
The path is printed under the table.
config:reset
Put a setting back to its default.
config:reset [name]
[name]the setting to put back; omit it to reset every one
Settings are remembered between runs, so restarting no longer undoes one. This is what undoes it — for a single setting, or for all of them at once.
A setting back at its default is dropped from the stored file rather than written out as a default, so a default that moves in a later release reaches you.
Examples
config:reset limit
config:reset
config:set
Change one of the settings.
config:set <name> [value]
namethe setting to change; ‘name=value’ in one word also works
[value]its new value — on/off for a switch, a number otherwise
‘config:set limit 50’ and ‘config:set limit=50’ do the same thing.
The change lasts for the session and no longer. Run ‘config:list’ to see what can be set, and what each one does.
Examples
config:set limit 50
config:set hex on
config:set writable_only=true
Pointers
Follow pointer chains, and find ones that survive a restart.
picklock> pointer:scan #1 --depth 3
+-----+-------------------+---------+--------------------+
| ROW | BASE | OFFSETS | TARGET |
+-----+-------------------+---------+--------------------+
| #1 | game.exe+0x3BA228 | 0x3E8 | 0x00000201A4C0F118 |
+-----+-------------------+---------+--------------------+
1 row in set (6.18 sec)
pointer:deref
Walk a pointer chain and print the address it lands on.
pointer:deref <base> [offset ...]
basethe static base of the chain, as an address expression — usually module+offset (see ‘help address’)
[offset ...]offsets to walk, in order; hex accepted. The last one is added without a final read, matching the Cheat Engine convention
Reads the pointer at BASE, adds the first offset, reads the pointer there, and so on; the last offset is added without a final read — the Cheat Engine convention, so a chain copied from a cheat table works unchanged.
Examples
pointer:deref game.exe+0x1a2b3c 0x10 0x8
pointer:deref 0x7ffee3a01000 0x18
pointer:diff
Intersect pointer-path files from several runs.
pointer:diff [file ...]
[file ...]two or more JSON files written by ‘pointer:save’, one per run of the target
Keeps only the paths present in every file, compared by their portable recipe (module, module offset, offsets) rather than by absolute address. Two or three runs of the same target usually leave a handful of paths standing, and those are the reliable ones.
The result replaces the paths currently held, so ‘pointer:save’ can write it straight back out.
Examples
pointer:diff run1.json run2.json
pointer:diff run1.json run2.json run3.json
pointer:load
Load pointer paths from a file.
pointer:load <file>
filepath of a JSON file written by ‘pointer:save’
Replaces the paths currently held. Each base is rebased onto the module addresses of the running target, so a file saved before a restart resolves correctly after it.
Examples
pointer:load health.json
pointer:paths
Show the pointer paths currently held.
pointer:paths [--limit N] [--page N] [--all]
-l, --limit Nrows per page, overriding the ‘limit’ setting
-p, --page Nwhich page to show, counting from 1
-a, --allprint every row, ignoring the limit
Lists the paths from the last ‘pointer:scan’, ‘pointer:load’, ‘pointer:rescan’ or ‘pointer:diff’. TARGET is where each one resolves right now, so a path that has gone stale shows as ‘(unresolved)’.
pointer:read
Read or write the value at the end of a pointer chain.
pointer:read <base> [offset ...] [--type TYPE] [--length N] [--write VALUE]
basethe static base of the chain, as an address expression — usually module+offset (see ‘help address’)
[offset ...]offsets to walk, in order; hex accepted. The last one is added without a final read, matching the Cheat Engine convention
--type TYPEvalue type at the end of the chain; defaults to int32
--length Nbyte width, required for the ‘string’ and ‘bytes’ types
--write VALUEwrite this value at the end of the chain instead of reading it
The one-line form of ‘pointer:deref’ followed by ‘memory:read’.
The chain is re-walked on every call, which is the point: it keeps working after the target reallocates whatever the last link pointed at.
Examples
pointer:read game.exe+0x1a2b3c 0x10 0x8 --type int32
pointer:read game.exe+0x1a2b3c 0x10 --write 999
pointer:rescan
Keep only the paths that still reach an address.
pointer:rescan <address> [file]
addressthe address the surviving paths must reach, as an address expression — usually ‘#1’ from the scan that found it again
[file]rescan the paths in this file; without it, the paths currently held are rescanned
The step that separates a real pointer path from a coincidence. Restart the target, find the value’s new address, then rescan the saved paths against it: the ones that still land on the address are the ones that describe the structure rather than that one run.
Examples
pointer:rescan #1
pointer:rescan 0x7ffee3a01000 health.json
pointer:save
Save the current pointer paths to a file.
pointer:save <file>
filepath of the JSON file to write
Writes the paths as JSON, keeping the module name and module-relative offset of each base so the file survives ASLR and can be re-used after the target restarts.
Examples
pointer:save health.json
pointer:scan
Find static pointer paths that reach an address.
pointer:scan <address> [--depth N] [--max-offset N] [--max N] [--unaligned] [--all-regions]
addressthe address to find paths to, as an address expression — usually ‘#1’ straight from a scan
--depth Nmaximum number of links in a chain (default 3). Each extra level costs a lot of time and memory
--max-offset Nlargest offset to consider (default 1024)
--max Nstop after N paths
--unalignedalso consider pointers not on a pointer-size boundary — slower, and rarely needed
--all-regionsinclude non-writable regions in the pointer map
Builds a map of every pointer in the target and walks it backwards from ADDRESS until it reaches a static base inside a module. The paths found replace whatever ‘pointer:paths’ was showing.
This is the expensive command in Picklock: minutes and hundreds of megabytes on a large target. Ctrl+C stops it and keeps the paths found so far.
A path is only worth trusting once it has survived a restart: save the paths, restart the target, find the address again, and run ‘pointer:rescan’ — see ‘help pointer:rescan’.
Examples
pointer:scan #1
pointer:scan 0x7ffee3a01000 --depth 4 --max 200
The session itself
The handful of words you type between doing real work. These have no namespace: they are not a subject to go looking through.
clear
Clear the terminal.
clear
Also answers to cls.
Takes no arguments.
Wipes the screen and the scrollback, the way the shell’s own ‘clear’ does. Nothing about the session changes: the process stays attached, the scan results and pointer paths are all still there.
To discard the scan results instead, that is ‘reset’ (scan:reset).
Does nothing when the output is redirected — escape codes in a log file would be vandalism rather than tidying.
exit
Leave the shell.
exit
Also answers to quit.
Takes no arguments.
Detaches from the target first. Ctrl+C and Ctrl+D at the prompt do the same thing, except for the status they exit with: 130 for Ctrl+C, the conventional ‘interrupted’ value, and 0 for the other two.
Ctrl+C means something different during a command — it abandons that command and returns to the prompt, keeping whatever a scan had already found. So interrupting a scan costs one keystroke and leaving costs two.
help
List the commands, or describe one.
help [topic]
Also answers to ?, \h.
[topic]a command name, or one of the topics ‘types’, ‘address’ and ‘scanning’. Omit it to list every command
With a command name, prints that command’s usage, every argument and flag it accepts, and examples. Typing ‘
The argument list is generated from the command’s own parser, so it is always what the command actually accepts.
Examples
help
help scan
help address
source
Run the commands in a file.
source <file>
Also answers to \..
filea text file of commands, one per line; blank lines and lines starting with ‘#’ or ‘–’ are ignored
Reads the file and runs each line as if it had been typed.
A failing line stops the script — a setup that half-ran is worse than one that says where it stopped.
Examples
source setup.txt
version
Print the Picklock, PyMemoryEditor, Python and platform versions.
version
Takes no arguments.
The four lines to quote in a bug report. Picklock is a client, so which PyMemoryEditor is underneath matters as much as which Picklock is on top — the two move independently.