Skip to content

Commit

Permalink
Fix disassembly of Thumb code
Browse files Browse the repository at this point in the history
Fix handling of emtpy command lines
Add Mem class for handling memory read/writes
Ensure we always allocate at least a page when creating working space
Change read and write commands to take length
Changes to move source code to different directories
Update docs
Add commandlet for display file descriptors
Add support for loading init script
Add support for loading new commandlets from JS
Support comments
  • Loading branch information
Your Name committed Apr 23, 2024
1 parent 8323c71 commit 14811f8
Show file tree
Hide file tree
Showing 51 changed files with 1,235 additions and 538 deletions.
12 changes: 12 additions & 0 deletions .cshellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# allocate some memory, assign a variable and dump it
malloc 32
v p ret
d p

# load a new commandlet from a script file and execute
src src.js
test malloc

# show the first instruction of exit
l exit 1

143 changes: 143 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Development
All of the commands supported by `frida-cshell` are implemented as commandlets. A list of available commands can be seen by running `help`:
```
-> help
breakpoints:
@F : function exit breakpoint
@f : function entry breakpoint
@i : instruction breakpoint
@r : memory read breakpoint
@w : memory write breakpoint
R : register management
data:
cp : copy data in memory
d : dump data from memory
l : disassembly listing
r : read data from memory
w : write data to memory
math:
& : and two operands
* : multiply two operands
+ : add two operands
- : subtract two operands
/ : divide two operands
<< : shl op1 by op2
>> : shr op1 by op2
^ : xor two operands
| : or two operands
~ : bitwise not
memory:
sym : look up a symbol information
vm : display virtual memory ranges
misc:
h : command history
help : print this message
v : variable management
modules:
ld : load modules
mod : display module information
thread:
bt : display backtrace information
t : display thread information
For more information about a command use:
help <cmd>
ret: 0x00000000 0
```
# Interface
Commandlets all implement the following interface:
```js
export abstract class CmdLet {
public abstract readonly category: string;
public abstract readonly name: string;
public abstract readonly help: string;
public readonly visible: boolean = true;
public abstract usage(): Var;
public abstract run(tokens: Token[]): Var;
public isSupported(): boolean {
return true;
}
}
```
## Members
* The `category` field is used to group the commandlets in the `help` output.
* The `name` field is used to determine the command name which must be entered by the user.
* The `help` field contains the string printed alongside the command in the `help` output
* The `visible` field dictates whether the commandlet is visible in the help menu.
* The `usage` method is called when the user enters `help <cmd name>` to print more detailed usage information to the console.
* The `run` method is called when the user executes the command, it is passed the `tokens` which have been passed as arguments.
* The `isSupported` method is called during initialization to allow it to determine whether it should be ignored, e.g. if the command only works on a subset of operating systems or architectures.

# Tokens
The token class represents each token the user has entered on the command line (each separated by whitespace). The `getLiteral` method can be used to retrieve the original string which the user typed. Otherwise, the `toVar` method can be used to interpret the value as a `Var` type.
```js
export class Token {
...
public getLiteral(): string;
public toVar(): Var | undefined;
...
}
```

# Var
The `Var` class represents the parameters passed to a commandlet after their interpretation by `frida-cshell`. Each can be accessed as either a `UInt64` or a `NativePointer` type. Note that `UInt64` is used in place of `number` since the number type loses precision handling numbers greater than `2^52`.

When converting tokens, `frida-cshell` will automatically convert several types of input:
1. Double-quoted strings will be interpreted and copied into memory. The `toPointer` method of these can then be used to reference the UTF-8 string data.
2. Numeric types are parsed from their string form. These can either be:
* Hexadecimal numbers with a `0x` or `0X` prefix
* Decimal numbers with a `0d` or `0D` prefix
* Octal numbers with a `0o` or `0O` prefix
* Decimal numbers without a prefix
3. Register names starting with a `$` prefix (these are only available during breakpoint execution).
4. Names variables which have been created using the `v` command.
5. Exported function names
6. Debug symbol names

Each of these types of input is handled transparently by `frida-cshell` and passed to the commandlet in a single consistent form.

```js
export class Var {
...
public toPointer(): NativePointer;
public toU64(): UInt64;
...
}
```

Similarly, the `run` method of each commandlet is expected to return a `Var` type which can subsequently be referenced by the user using the `ret` keyword in the execution of the next command.

# Parsing
Below is snippet of the `dump` commandlet showing how it parses it's two arguments. The first is the address which to dump and the second is the length. Note that the first argument is also used as the return value for this commandlet. Note also that the second argument is also converted from a `UInt64` to a `number` type, since this is what is reqired by the `hexdump` function called by `this.dump`. This is used in many commands where the parameter is likely to be a small number and therefore loss of precision is not a concern.
```js
private runWithLength(tokens: Token[]): Var | undefined {
if (tokens.length != 2) return undefined;

const t0 = tokens[0]?.toVar();
if (t0 === undefined) return undefined;

const address = t0.toPointer();
if (address === undefined) return undefined;

const length = tokens[1]?.toVar()?.toU64().toNumber();
if (length === undefined) return undefined;

this.dump(address, length);
return t0;
}

public run(tokens: Token[]): Var {
const retWithLength = this.runWithLength(tokens);
if (retWithLength !== undefined) return retWithLength;

...

return this.usage();
}
```
# Scripts
Whilst scripts can be written in Typescript and added to the project, for more adhoc use cases, it is also possible to write commandlets in JavaScript and load them dynamically into `frida-cshell`. An example script can be seen [here](src.js). Note that all of the exported classes within `frida-cshell` should also be available to these scripts. These scripts can be loaded using the `src` command, simply passing the filename to be loaded.
# Initialization
To automate this process, it is also possible to provide a [`.cshellrc`](assets/initrd/.cshellrc) file in your home directory containing commands to execute during start-up. This can include the use of the `src` command and the subsequent execution of any commandlets loaded as a result.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ COPY assets/initrd/group /root/initramfs/etc/group
COPY assets/initrd/passwd /root/initramfs/etc/passwd
COPY assets/initrd/motd /root/initramfs/etc/motd
COPY assets/initrd/.profile /root/initramfs/.profile
COPY assets/initrd/.cshellrc /root/initramfs/.cshellrc
COPY assets/initrd/entropy.c /root/entropy.c

################################################################################
Expand Down Expand Up @@ -564,4 +565,4 @@ ENTRYPOINT ["/bin/vm-x86"]
# CSHELL-x64 #
################################################################################
FROM cshell as cshell-x64
ENTRYPOINT ["/bin/vm-x64"]
ENTRYPOINT ["/bin/vm-x64"]
89 changes: 61 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,46 @@ Attached to:
```
**Important** Be sure to include the `--interactive` command line option, otherwise the terminal will appear non-responsive.

# Wrapper
Alternatively, included in the release is a wrapper shell script `frida-cshell`:
```
# ./frida-cshell -h
Usage
./frida-cshell [OPTION?]
Help Options:
-h, show help options
Application Options:
-f spawn FILE
-n attach to NAME
-p attach to PID
-V enable verbose mode
```
It assumes that `frida-inject` can be found on the path, otherwise an alternative can be provided using the `FRIDA_INJECT` environment variable. As an example, it can be used as follows:

```
# FRIDA_INJECT=frida-inject-64 ./frida-cshell -f ./target
_.---._ _ _ _
.'"".'/|\'.""'. | | | | |
: .' / | \ '. : ____ ___| |__ ___| | |
'.' / | \ '.' / _ / __| '_ \ / _ \ | |
`. / | \ .' | (__\__ \ | | | |__/ | |
`-.__|__.-' \____|___/_| |_|\___|_|_|
CSHELL v1.0.6, running in FRIDA 0.0.0 using QJS
Attached to:
PID: 253520
Name: target
->
```
# Init Scripts
Commands which should be run on start-up can be provided in a file name `.cshellrc` in the current directory. An example can be found [here](assets/initrd/.cshellrc)

# Development
For documentation on how to develop `frida-cshell`, or provide additional commandlets via script files, see [here](DEVELOPMENT.md)

# Walkthrough
Perhaps the easiest way to understand the C-Shell is by an example, let's walk through a fictional sequence of commands to analyse a program
## #0 Threads
Expand Down Expand Up @@ -172,7 +212,7 @@ ret: 0x00007f14`88000cb0 (139726157778096)

Now let's copy some data in:
```
->w8 p 0xddccbbaa11223344
->w 8 p 0xddccbbaa11223344
Wrote value: 0xddccbbaa`11223344 = 15982355516737336132 to 0x00007f14`88000cb0
ret: 0x00007f14`88000cb0 (139726157778096)
Expand Down Expand Up @@ -360,7 +400,7 @@ Let's see how many bytes are being allocated, we will set a function entry break
Created #1 . function entry 0x00007f00`18dbb0a0: malloc [hits:1]

Type 'q' to finish, or 'x' to abort
- r rdi
- R rdi
- q

ret: 0x00007f00`18dbb0a0 139638393778336
Expand Down Expand Up @@ -411,7 +451,7 @@ ret: 0x00007fe2`821090c9 140610821460169
Created #1 . instruction 0x00007fe2`821090ab: 0x00007fe2`821090ab [hits:1]

Type 'q' to finish, or 'x' to abort
- r
- R
- q

ret: 0x00007fe2`821090ab 140610821460139
Expand Down Expand Up @@ -496,7 +536,7 @@ ret: 0x00007fe2`68000c90 140610384170128
Created #1 . function exit 0x00007fe2`821090a0: malloc [hits:1]

Type 'q' to finish, or 'x' to abort
- r ret p
- R ret p
- q

ret: 0x00007fe2`821090a0 140610821460128
Expand Down Expand Up @@ -653,16 +693,6 @@ Break #1 [instruction] @ $pc=0x00007f36`fd87ee48, $tid=1163391
ret: 0x00000000`00000000 0
->
```
# TODO
Commandlets not yet implemented:
* `fd` - Show open file descriptors (for Unix like OS)
* `src` - Support loading Javascript from file to augment the set of supported Commandlets.
Others
* Support for modifying write protected memory
* Add support for display exception information in the event of an unhandled signal
# Commands
In contrast to a conventional shell, commands are not processes to be executed, but rather functions. `C` functions within the target application. For example, we can call `malloc` to provide us some memory as follows:
Expand Down Expand Up @@ -690,19 +720,20 @@ ret: 0x00007f58`64000c70 (140017611574384)
# Commandlets
As well as being able to directly call functions in `C`, the C-Shell also provides a number of Commandlets, we can see a list of these by running the `help` command:
```
->help
-> help
breakpoints:
@F : function exit breakpoint
@f : function entry breakpoint
@i : instruction breakpoint
@r : memory read breakpoint
@w : memory write breakpoint
R : register management
data:
cp : copy data in memory
d : dump data from memory
l : disassembly listing
r1 : read a byte from memory
r2 : read a half from memory
r4 : read a word from memory
r8 : read a double word from memory
w1 : write a byte to memory
w2 : write a half to memory
w4 : write a word to memory
w8 : write a double word to memory
r : read data from memory
w : write data to memory
math:
& : and two operands
* : multiply two operands
Expand All @@ -715,21 +746,23 @@ math:
| : or two operands
~ : bitwise not
memory:
mod : display module information
sym : look up a symbol information
vm : display virtual memory ranges
misc:
h : command history
help : print this message
v : variable management
modules:
ld : load modules
mod : display module information
thread:
bt : display backtrace information
t : display thread information

For more information about a command use:
help <cmd>

ret: 0x00000000`00000000 (0)
ret: 0x00000000 0
```
For more details on any command we can run `help <cmd>`, e.g.
Expand Down Expand Up @@ -853,7 +886,7 @@ ret: 0x00007fcf`b0000c70 (140529987751024)
ret: 0x00007fcf`b0000c70 (140529987751024)
```
```
->w8 0x00007fcf`b0000c70 0xaabbccdd`11223344
->w 8 0x00007fcf`b0000c70 0xaabbccdd`11223344
Wrote value: 0xaabbccdd`11223344 = 12302652056939934532 to 0x00007fcf`b0000c70

ret: 0x00007fcf`b0000c70 (140529987751024)
Expand Down Expand Up @@ -896,7 +929,7 @@ ret: 0x00007f14`88000c70 (139726157778032)
ret: 0x00007f14`88000c70 (139726157778032)
```
```
->w8 p 0xaabbccdd11223344
->w 8 p 0xaabbccdd11223344
Wrote value: 0xaabbccdd`11223344 = 12302652056939934532 to 0x00007f14`88000c70

ret: 0x00007f14`88000c70 (139726157778032)
Expand Down Expand Up @@ -928,7 +961,7 @@ ret: 0x00007f14`88000c90 (139726157778064)
ret: 0x00007f14`88000c90 (139726157778064)
```
```
->w8 ret 0xaabbccdd`11223344
->w 8 ret 0xaabbccdd`11223344
Wrote value: 0xaabbccdd`11223344 = 12302652056939934532 to 0x00007f14`88000c90

ret: 0x00007f14`88000c90 (139726157778064)
Expand Down
12 changes: 12 additions & 0 deletions assets/initrd/.cshellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# allocate some memory, assign a variable and dump it
malloc 32
v p ret
d p

# load a new commandlet from a script file and execute
src /home/ws/src.js
test malloc

# show the first instruction of exit
l exit 1

Loading

0 comments on commit 14811f8

Please sign in to comment.