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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ index.tex
/site_libs/
/index_files/
/docs/*

**/*.quarto_ipynb
2 changes: 2 additions & 0 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ book:
- src/configuration/initial_scripts.md
- src/configuration/compile_time_variables.md
- src/configuration/run_time_variables.md
- src/configuration/global_variables.md


- part: "Basic Commands"
chapters:
Expand Down
100 changes: 100 additions & 0 deletions src/configuration/global_variables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Global Variables(`avg` Commands)

Global variables are declared outside of any function or block and are accessible throughout the entire program. They persist for the full duration of execution.

In reverse engineering, identifying global variables:

- Improves code readability
- Makes cross-references easier to follow
- Helps with data-flow and structure analysis

**Important:**
> In Rizin, global variables are identified during analysis.
> Run `aa` or `aaa` before using `avg` commands, otherwise no globals will appear.

The help command to list all `avg` commands is: `avg?`
```
avgl[jqt] [<var_name>] # show/list global variables
avga <var_name> <type> # add global variable manually
avgd <addr> # delete the global variable at the addr
avgm <name> # delete global variable with name
avgn <old_var_name> <new_var_name> # rename the global variable
avgp <name> # print the global variable value
avgt <var_name> <type> # change the global variable type
avgx[jq] <name> # print all xrefs to the global variable
```

```
avgl [<var_name>] # show/list global variables
avglj [<var_name>] # show/list global variables (JSON mode)
avglq [<var_name>] # show/list global variables (quiet mode)
avglt [<var_name>] # show/list global variables (table mode)
```
There are 3 modes of display. Which helps in a better analysis and view the variables.

**Adding Global Variables**

`avga <var_name> <type>` This command lets you manually add global variables with their name and type.

You use then when a global variables is missed during the analysis. Here `<type>` means the datatype of the variable. Example: `int`, `char`, `long`.

This manually defines a global variable when Rizin’s automatic analysis did not detect it.

**Printing Global Variables**

`avgp <name>` reads memory at the address of the specified global variable and displays its current value.
>In debug mode → shows the value at the current breakpoint.
Copy link
Member

Choose a reason for hiding this comment

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

Have you tried this btw?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I tested it using a small C program with a global variable. The behavior works as expected, but my wording was inaccurate I should have said that in debug mode the value is read from process memory, rather than writing that it corresponds to a specific breakpoint location.

Copy link
Member

Choose a reason for hiding this comment

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

Can you open a PR in Rizin which adds this test please?
Because we don't have one and this is a pretty essential thing to check.

the binary with source code should be added in rizin-testbins repo.

Would really appreciate it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure i can do that,

// test.c
#include <stdio.h>

int test_global = 1337;

int main() {
    printf("Ready: %d\n", test_global); 
    return 0;
}
rizin -d test.exe
Spawned new process with pid 30760, tid = 21376
 -- Save your projects with 'Ps <project-filename>' and restore then with 'Po <project-filename>'
[0x7ffc8970c510]> aaa
[WARNING: invalid address from 0x7ff7465b1500entry0 (aa)
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls
[x] Analyze len bytes of instructions for references
[x] Analyze local variables and arguments
[WARNING: core: analysis propagation type can't be exectured when in debugger mode.
[x] Type matching analysis for all functions
[x] Applied 0 FLIRT signatures via sigdb
[x] Propagate noreturn information
[x] Check for classes
[x] Integrate dwarf function information.
[x] Resolve pointers to data sections
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x7ffc8970c510]> s sym.main
[0x7ff7465b1450]> db
[0x7ff7465b1450]> dc
ERROR: Cannot create flag "teb.40716" at 0x7117ace000 because there is already "PRIVATE__..7117ace000" flag
[0x7ffc8979f4ee]> avgp test_global
 int : 0x140003000 = -1

As you can see while debugging the value of test_global was stored as -1 in the process memory. Hence avgp prints that value instead of test_global.
@Rot127 please check once is this correct?

Copy link
Member

Choose a reason for hiding this comment

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

No, it is not.

#include <stdio.h>

int test_global = 1337;

int main() {
    printf("Ready: %d\n", test_global); 
    test_global = 1;
    printf("Ready: %d\n", test_global); 
    return 0;
}

Before the first printf call it should print 1337 (and it does for me).
Then it sets it to 1.
Before the second printf call it should print 1. But for me it still prints 1337.


>Without debugging → shows the value stored in the binary.


**Changing Variable Type**

`avgt <var_name> <type>` This command lets you change the data-type of the variable.

Note: The correct data-type must be used which helps in improving output, cross-reference accuracy and structure recovery.

There are two modes of display quiet and JSON.

### Example:

```
# Ran 'avglt' to check for existing global variables(none were present).
[0x00001040]> avglt
name type size address decl_file decl_line decl_col
――――――――――――――――――――――――――――――――――――――――――――――――――――
[0x00001040]> avga test_variable int
[0x00001040]> avglt
name type size address decl_file decl_line decl_col
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
test_variable int 0x4 0x1040 - -1 -1
[0x00001040]> avgp test_variable
int : 0x00001040 = 3644689736
[0x00001040]> avgt test_variable char
[0x00001040]> avgp test_variable
char : 0x00001040 = 'H'
[0x00001040]> avgn test_variable renamed_variable
[0x00001040]> avglt
Copy link
Member

Choose a reason for hiding this comment

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

Example is good.

But I would suggest to move the description into here. It is easier to follow this way.

# Ran 'avglt' to check for existing global variables (none were present).
[0x00001040]> avglt

# Step ...
[0x00001040]> COMANND

name type size address decl_file decl_line decl_col
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
renamed_variable char 0x1 0x1040 - -1 -1
[0x00001040]> avgx renamed_variable
[0x00001040]> avgm renamed_variable
[0x00001040]> avglt
name type size address decl_file decl_line decl_col
――――――――――――――――――――――――――――――――――――――――――――――――――――
```

### What Was Done in This Example

- Ran `avglt` to check for existing global variables (none were present).
- Used `avga test_variable int` to manually create a new global variable of type `int`.
- Ran `avglt` again to confirm the variable was successfully added.
- Used `avgp test_variable` to print the value at that memory location as an `int`.
- Changed the variable type with `avgt test_variable char`.
- Printed the value again using `avgp test_variable`, now interpreted as a `char` (`'H'`), showing how type affects data interpretation.
- Renamed the variable using `avgn test_variable renamed_variable`.
- Ran `avglt` to verify the variable name and updated type were reflected.
- Used `avgx renamed_variable` to check for cross-references (none found since it was manually added).
- Deleted the variable using `avgm renamed_variable`.
- Ran `avglt` one final time to confirm the global variable list was empty again.
2 changes: 2 additions & 0 deletions src/refcard/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Global variables appear after auto-analysis or after adding them manually.
| avgp name | Print global variable |
| avgx name | Show xrefs to the global |

For more info check the [global variable documentation](/src/configuration/global_variables.md).

## Information

Binary files have information stored inside the headers. The `i` command uses the RzBin API and allows us to the same things rz-bin does. Those are the most common ones.
Expand Down