[Radare2 Framework] Command-line Options, Basic Command, Expressions

Command-line Options

Radare2 프레임워크를 설치하고 터미널에 radare2 -hr2 -h라고 입력을 하면 다음과 같은 다양한 옵션이 있다는 것을 확인할 수 있습니다.

앞으로 radare2 대신 r2를 사용하겠습니다.


r2 -h
Usage: r2 [-ACdfLMnNqStuvwzX] [-P patch] [-p prj] [-a arch] [-b bits] [-i file]
          [-s addr] [-B baddr] [-m maddr] [-c cmd] [-e k=v] file|pid|-|--|=
 --           run radare2 without opening any file
 -            same as 'r2 malloc://512'
 =            read file from stdin (use -i and -c to run cmds)
 -=           perform !=! command to run all commands remotely
 -0           print \x00 after init and every command
 -2           close stderr file descriptor (silent warning messages)
 -a [arch]    set asm.arch
 -A           run 'aaa' command to analyze all referenced code
 -b [bits]    set asm.bits
 -B [baddr]   set base address for PIE binaries
 -c 'cmd..'   execute radare command
 -C           file is host:port (alias for -c+=http://%s/cmd/)
 -d           debug the executable 'file' or running process 'pid'
 -D [backend] enable debug mode (e cfg.debug=true)
 -e k=v       evaluate config var
 -f           block size = file size
 -F [binplug] force to use that rbin plugin
 -h, -hh      show help message, -hh for long
 -H ([var])   display variable
 -i [file]    run script file
 -I [file]    run script file before the file is opened
 -k [OS/kern] set asm.os (linux, macos, w32, netbsd, ...)
 -l [lib]     load plugin file
 -L           list supported IO plugins
 -m [addr]    map file at given address (loadaddr)
 -M           do not demangle symbol names
 -n, -nn      do not load RBin info (-nn only load bin structures)
 -N           do not load user settings and scripts
 -q           quiet mode (no prompt) and quit after -i
 -Q           quiet mode (no prompt) and quit faster (quickLeak=true)
 -p [prj]     use project, list if no arg, load if no file
 -P [file]    apply rapatch file and quit
 -r [rarun2]  specify rarun2 profile to load (same as -e dbg.profile=X)
 -R [rr2rule] specify custom rarun2 directive
 -s [addr]    initial seek
 -S           start r2 in sandbox mode
 -t           load rabin2 info in thread
 -u           set bin.filter=false to get raw sym/sec/cls names
 -v, -V       show radare2 version (-V show lib versions)
 -w           open file in write mode
 -x           open without exec-flag (asm.emu will not work), See io.exec
 -X           same as -e bin.usextr=false (useful for dyldcache)
 -z, -zz      do not load strings or load them even in raw

모든 옵션에 대해서 제가 설명을 해드리면 좋겠지만 아직 저도 공부하는 입장으로 제가 이해한 옵션만 설명하도록 하겠습니다.


가장 먼저 알아볼 옵션은 -L입니다. -L옵션을 보면 list supported IO plugins이라고 되어있는데, 말 그대로 현재 시스템에 설치된 r2에서 입출력이 가능한 모든 파일 목록을 출력하는 옵션입니다.


 r2 -L
rw_  ar       Open ar/lib files [ar|lib]://[file//path] (LGPL3)
rw_  bfdbg    BrainFuck Debugger (bfdbg://path/to/file) (LGPL3)
rwd  bochs    Attach to a BOCHS debugger (LGPL3)
r_d  debug    Native debugger (dbg:///bin/ls dbg://1388 pidof:// waitfor://) (LGPL3) v0.2.0 pancake
rw_  default  open local files using def_mmap:// (LGPL3)
rwd  gdb      Attach to gdbserver, 'qemu -s', gdb://localhost:1234 (LGPL3)
rw_  gprobe   open gprobe connection using gprobe:// (LGPL3)
rw_  gzip     read/write gzipped files (LGPL3)
rw_  http     http get (http://rada.re/) (LGPL3)
rw_  ihex     Intel HEX file (ihex://eeproms.hex) (LGPL)
r__  mach     mach debug io (unsupported in this platform) (LGPL)
rw_  malloc   memory allocation (malloc://1024 hex://cd8090) (LGPL3)
rw_  mmap     open file using mmap:// (LGPL3)
rw_  null     null-plugin (null://23) (LGPL3)
rw_  procpid  /proc/pid/mem io (LGPL3)
rwd  ptrace   ptrace and /proc/pid/mem (if available) io (LGPL3)
rwd  qnx      Attach to QNX pdebug instance, qnx://host:1234 (LGPL3)
rw_  r2k      kernel access API io (r2k://) (LGPL3)
rw_  r2pipe   r2pipe io plugin (MIT)
rw_  r2web    r2web io client (r2web://cloud.rada.re/cmd/) (LGPL3)
rw_  rap      radare network protocol (rap://:port rap://host:port/file) (LGPL3)
rw_  rbuf     RBuffer IO plugin: rbuf:// (LGPL)
rw_  self     read memory from myself using 'self://' (LGPL3)
rw_  shm      shared memory resources (shm://key) (LGPL3)
rw_  sparse   sparse buffer allocation (sparse://1024 sparse://) (LGPL3)
rw_  tcp      load files via TCP (listen or connect) (LGPL3)
rwd  windbg   Attach to a KD debugger (windbg://socket) (LGPL3)
rwd  winedbg  Wine-dbg io and debug.io plugin for r2 (MIT)
rw_  zip      Open zip files [apk|ipa|zip|zipall]://[file//path] (BSD)

첫번째 컬럼은 권한입니다. r,w,d 옵션이 있는데 각각 read, write, debug입니다. 즉 rw의 경우 읽기와 쓰기가 가능하다는 의미이며 rwd는 읽기, 쓰기, 디버깅이 가능하다는 의미입니다. 두번째 컬럼은 이름입니다. 세번째 컬럼은 해당 플러그인에 대한 설명이며 마지막 컬럼은 라이선스입니다.


---는 전부, r2를 파일없이 r2를 실행하는 옵션입니다. 이 둘의 차이점은 --의 경우 말 그대로 r2를 실행만 하며 -의 경우 512바이트의 버퍼를 확보하고 r2를 실행을 합니다.


r2 --       
 -- The door is everything ...
[0x00000000]> s 512-16; px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x000001f0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000200  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000210  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000220  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000230  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000240  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000250  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000260  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000270  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000280  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000290  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002a0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002b0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002c0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002d0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002e0  ffff ffff ffff ffff ffff ffff ffff ffff  ................

r2 -
 -- 256 colors ought to be enough for anybody
[0x00000000]> s 512-16; px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x000001f0  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x00000200  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000210  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000220  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000230  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000240  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000250  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000260  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000270  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000280  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x00000290  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002a0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002b0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002c0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002d0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x000002e0  ffff ffff ffff ffff ffff ffff ffff ffff  ................

s 512-16; px 이 뭔가요?

s 512-16; px의 경우 s 516명령와 px명령어를 ;으로 결합하여 실행을 한 것으로 sseek로 주어진 주소로 커서를 옮기는 것이고 pxprint hex로 헥사뷰어 형태로 커서로부터 오프셋Offset까지 출력을 해주는 명령어 입니다. 자세한 것에 대해서는 radare2의 헥사 에이터 기능을 살펴볼 때 설명하도록 하겠습니다

차이점을 보면 아시겠지만 r2 -의 경우 512바이트의 공간을 확보를 하고 0으로 초기화를 하였습니다. 그와 반면에 r2 --의 경우 공간을 확보하지 않았기 때문에 전부 FF로 채워져 있음을 확인할 수 있습니다.

직접 버퍼의 크기를 주고 싶어요!

직접 버퍼의 크기를 줘서 r2를 실행하는 방법은 간단합니다. 옵션에서 확인할 수 있듯이 r2 -r2 malloc://512와 같다고 나와있습니다. 즉 r2 malloc://N으로 실행을 하면 원하는 버퍼의 크기로 메모리를 확보해서 r2를 실행할 수 있습니다.


이제 알아볼 옵션은 -a, -b, -k 옵션입니다. 이 3개의 옵션은 바이너리 파일을 분석을 할때 지정하는 옵션으로 순서대로 아키택쳐(asm.arch), 비트(asm.bits), 운영체제(asm.os)를 선택하는 옵션입니다. 해당 옵션이 가질 수 있는 값의 경우 e asm.arch/bits/os=?e asm.arch/bits/os=??로 확인할 수 있습니다.

추후에 다루겠지만 자주 사용되거나 유명한 값은 다음과 같습니다. 참고로 asm.bits의 경우 아키택쳐에 따라 지원하지 않는 값이 존재할 수 있습니다.

  • asm.arch
    • arm
    • dalvik
    • java
    • mips
    • x86
  • asm.bits
    • 8
    • 16
    • 32
    • 64
  • asm.os
    • ios
    • darwin
    • linux
    • windows

바이너리 분석 및 디버깅 관련 옵션에는 -A, -d, -M, -n, -nn이 있습니다.

-A옵션을 붙힐 경우, r2 실행시 aaa명령을 실행합니다. aaa명령의 경우 바이너리 분석에서 더 자세히 설명을 하겠지만 간단하게 설명을 하자면 r2의 경우 바이너리 파일을 불러오면 자동으로 분석을 진행하지 않습니다. 이때 분석 명령어를 사용해서 분석을 진행을 해야 됩니다. 분석 명령어에 대해서는 나중에 더 자세하게 알아보도록 하겠습니다.

-d옵션은 위에서 서술한 입출력 플러그인에서 debug 플러그인과 동일합니다. 다른점은 플러그인의 경우 파일일 경우와 프로세스일 경우를 구분해서 사용해야 되지만 -d옵션의 경우 구분할 필요 없이 파일이름이나 PID를 주면 됩니다.

-M-n, -nn 옵션은 일반적인 옵션들과 달리 기본적으로 활성화 되어 있는 기능을 비활성화 하는 옵션입니다. -M의 경우 demangle이라고 하여 난독화 되어있는 C++ 심볼을 읽을 수 있게 변경하는 기능을 비활성화 하고 -n-nn은 바이너리 정적분석을 비활성화 합니다. 해당 옵션들은 r2를 헥사에디터로 사용할 때 사용하는 옵션들 입니다.


-w옵션은 파일을 쓰기가능한 상태로 여는 옵션입니다. 만약에 이 옵션을 붙히지 않고 r2를 실행하면 읽기전용이기 때문에 내부 커맨드 중 w 커맨드는 사용하지 못합니다.


CLI

이제 r2의 기본적인 유저 인터페이스에 대해 알아보도록 하죠. r2 -으로 r2를 실행하면 다음과 같은 쉘이 우리를 반겨줍니다.


 -- This incident will be reported
[0x00000000]>

첫번째 줄은 랜덤으로 나오는 구절입니다. 딱히 신경쓸 필요는 없습니다. 명령어를 입력하는 곳은 [0x00000000]> 이후 입니다. [0x00000000]는 커서입니다. 커서의 위치를 주소값으로 나타낸 것으로 디버깅할때는 현재 실행중인 함수를 가르키고 있습니다. 많이 착각하는게 있는데 IP가 아닌 함수의 주소를 가르키고 있습니다.


Basic Command

이제 ?를 치면 커맨드 포맷과 사용할 수 있는 명령어를 확인할 수 있습니다.


[0x00000000]> ?
Usage: [.][times][cmd][~grep][@[@iter]addr!size][|>pipe] ; ...   
Append '?' to any char command to get detailed help
Prefix with number to repeat command N times (f.ex: 3x)
| %var=value              alias for 'env' command
| *[?] off[=[0x]value]    pointer read/write data/values (see ?v, wx, wv)
| (macro arg0 arg1)       manage scripting macros
| .[?] [-|(m)|f|!sh|cmd]  Define macro or load r2, cparse or rlang file
| _[?]                    Print last output
| =[?] [cmd]              send/listen for remote commands (rap://, http://, <fd>)
| <[...]                  push escaped string into the RCons.readChar buffer
| /[?]                    search for bytes, regexps, patterns, ..
| ![?] [cmd]              run given command as in system(3)
| #[?] !lang [..]         Hashbang to run an rlang script
| a[?]                    analysis commands
| b[?]                    display or change the block size
| c[?] [arg]              compare block with given data
| C[?]                    code metadata (comments, format, hints, ..)
| d[?]                    debugger commands
| e[?] [a[=b]]            list/get/set config evaluable vars
| f[?] [name][sz][at]     add flag at current address
| g[?] [arg]              generate shellcodes with r_egg
| i[?] [file]             get info about opened file from r_bin
| k[?] [sdb-query]        run sdb-query. see k? for help, 'k *', 'k **' ...
| l [filepattern]         list files and directories
| L[?] [-] [plugin]       list, unload load r2 plugins
| m[?]                    mountpoints commands
| o[?] [file] ([offset])  open file at optional address
| p[?] [len]              print current block with format and length
| P[?]                    project management utilities
| q[?] [ret]              quit program with a return value
| r[?] [len]              resize file
| s[?] [addr]             seek to address (also for '0x', '0x1' == 's 0x1')
| t[?]                    types, noreturn, signatures, C parser and more
| T[?] [-] [num|msg]      Text log utility
| u[?]                    uname/undo seek/write
| V                       visual mode (V! = panels, VV = fcngraph, VVV = callgraph)
| w[?] [str]              multiple write operations
| x[?] [len]              alias for 'px' (print hexadecimal)
| y[?] [len] [[[@]addr    Yank/paste bytes from/to memory
| z[?]                    zignatures management
| ?[??][expr]             Help or evaluate math expression
| ?$?                     show available '$' variables and aliases
| ?@?                     misc help for '@' (seek), '~' (grep) (see ~??)
| ?>?                     output redirection

명령어 포맷은 vim과 유사합니다.


먼저 .은 명령어 실행결과를 실행해주는 접두어입니다. 쉘에서 ``이나 $()와 같은 역할을 하는 접두어입니다.


times는 정수가 오는데 뒤에 나오는 cmd를 정수만큼 반복을 합니다. 만약에 이 times가 비어있으면 1번만 실행을 합니다. 이것은 vim의 명령어와 같습니다. 아래 예제를 보면 times와 없는것과 times에 1로 준 것과 동일하게 한번만 실행이 됩니다. times를 3으로 주면 주어진 명령어를 3번 반복합니다.


[0x00000000]> px 16
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  0000 0000 0000 0000 0000 0000 0000 0000  ................
[0x00000000]> 1px 16
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  0000 0000 0000 0000 0000 0000 0000 0000  ................
[0x00000000]> 3px 16
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  0000 0000 0000 0000 0000 0000 0000 0000  ................
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  0000 0000 0000 0000 0000 0000 0000 0000  ................
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00000000  0000 0000 0000 0000 0000 0000 0000 0000  ................

cmd는 명령어 입니다. 명령어의 경우 ?를 치면 확인할 수 있듯이 일부 특수문자와 일부 대문자, h를 제외한 소문자를 명령어로 사용할 수 있습니다.


~grep은 쉘에서 | grep과 동일하지만 좀 더 다양한 기능을 가지고 있습니다. ~를 사용하는 방법과 옵션은 ~?으로 자세히 확인할 수 있습니다.


Usage: [command]~[modifier][word,word][endmodifier][[column]][:line]
modifier:   
|  &            all words must match to grep the line
|  $[n]         sort numerically / alphabetically the Nth column
|  $!           sort in inverse order
|  +            case insensitive grep (grep -i)
|  ^            words must be placed at the beginning of line
|  !            negate grep
|  ?            count number of matching lines
|  ?.           count number chars
|  ??           show this help message
|  :s..e        show lines s-e
|  ..           internal 'less'
|  ...          internal 'hud' (like V_)
|  {}           json indentation
|  {path}       json grep
|  {}..         less json indentation
endmodifier:
|  $            words must be placed at the end of line
column:
|  [n]          show only column n
|  [n-m]        show column n to m
|  [n-]         show all columns starting from column n
|  [i,j,k]      show the columns i, j and k
Examples:
|  i~:0         show first line of 'i' output
|  i~:-2        show the second to last line of 'i' output
|  i~:0..3      show first three lines of 'i' output
|  pd~mov       disasm and grep for mov
|  pi~[0]       show only opcode
|  i~0x400$     show lines ending with 0x400

사용방법은 명령어 뒤에 ~을 해주고 grep을 사용하듯이 문자열을 입력하면 됩니다. 옵션을 보면 알 수 있듯이 정규표현식을 일부 차용하고 있습니다. 사용방법은 예제와 함께 서술하겠습니다. 예제에 사용한 바이너리의 소스코드와 컴파일 옵션은 다음과 같습니다.


#include <stdio.h>

int main(void) 
{
    printf("Hello, Radare2!");
    return 0;
}

gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) 
gcc hello_r2.c -o hello_r2

먼저 r2 -A hello_r2로 진입할 경우 커서가 entry0를 가르키고 있습니다. 이를 main으로 옮겨줄 필요가 있습니다. main 주소를 찾는 방법은 간단합니다. -A 옵션을 사용했기 때문에 자동으로 코드 분석을 해줍니다. 이제 afl을 사용할 경우 바이너리 파일의 모든 함수의 주소를 확인할 수 있습니다. 해당 명령어를 통해 sys.main을 찾았다면 s를 통해 커서를 옮겨주면 됩니다. ~를 사용한 예제는 다음과 같습니다.


[0x00000540]> afl~main
0x00000000    3 97   -> 123  sym.imp.__libc_start_main
0x0000064a    1 28           sym.main
[0x00000540]> s 0x64a

이제 pdf를 입력하면 main을 디스어셈블링한 결과를 확인할 수 있습니다.


[0x0000064a]> pdf sym.main
            ;-- main:
/ (fcn) sym.main 28
|   sym.main (int argc, char **argv, char **envp);
|           ; DATA XREF from entry0 (0x55d)
|           0x0000064a      55             push rbp
|           0x0000064b      4889e5         mov rbp, rsp
|           0x0000064e      488d3d9f0000.  lea rdi, str.Hello__Radare2 ; 0x6f4 ; "Hello, Radare2!" ; const char *format
|           0x00000655      b800000000     mov eax, 0
|           0x0000065a      e8c1feffff     call sym.imp.printf         ; int printf(const char *format)
|           0x0000065f      b800000000     mov eax, 0
|           0x00000664      5d             pop rbp
\           0x00000665      c3             ret

먼저 찾을 단어 중간에 ,을 삽입하면 or과 같습니다. 둘중 하나라도 포함되면 전부 출력을 합니다. 예를 들면 다음과 같습니다.


[0x0000064a]> pdf ~rbp,rsp
|           0x0000064a      55             push rbp
|           0x0000064b      4889e5         mov rbp, rsp
|           0x00000664      5d             pop rbp

이런식으로 범용레지스터와 rbp, rsp가 어디에서 사용하는지를 확인할 수 있습니다. or 역할을 하는 명령어가 있다면 당연히 and역할을 하는 명령어도 있습니다. 이것은 간단하게 찾을 단어 앞에 &을 붙히면 됩니다.


[0x0000064a]> pdf ~&rbp,rsp
|           0x0000064b      4889e5         mov rbp, rsp

$$!은 결과를 오름차순, 내림차순으로 정렬을 하는 수식어입니다. 예를 들면 다음과 같습니다. 아무런 정수를 주지 않을 경우 첫번째 칼럼을 기준으로 정렬을 해서 결과를 출력합니다.


[0x0000064a]> px ~$
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x0000064a  5548 89e5 488d 3d9f 0000 00b8 0000 0000  UH..H.=.........
0x0000065a  e8c1 feff ffb8 0000 0000 5dc3 662e 0f1f  ..........].f...
0x0000066a  8400 0000 0000 4157 4156 4989 d741 5541  ......AWAVI..AUA
0x0000067a  544c 8d25 3607 2000 5548 8d2d 3607 2000  TL.%6. .UH.-6. .
0x0000068a  5341 89fd 4989 f64c 29e5 4883 ec08 48c1  SA..I..L).H...H.
0x0000069a  fd03 e84f feff ff48 85ed 7420 31db 0f1f  ...O...H..t 1...
0x000006aa  8400 0000 0000 4c89 fa4c 89f6 4489 ef41  ......L..L..D..A
0x000006ba  ff14 dc48 83c3 0148 39dd 75ea 4883 c408  ...H...H9.u.H...
0x000006ca  5b5d 415c 415d 415e 415f c390 662e 0f1f  []A\A]A^A_..f...
0x000006da  8400 0000 0000 f3c3 0000 4883 ec08 4883  ..........H...H.
0x000006ea  c408 c300 0000 0100 0200 4865 6c6c 6f2c  ..........Hello,
0x000006fa  2052 6164 6172 6532 2100 011b 033b 3800   Radare2!....;8.
0x0000070a  0000 0600 0000 0cfe ffff 8400 0000 2cfe  ..............,.
0x0000071a  ffff ac00 0000 3cfe ffff 5400 0000 46ff  ......<...T...F.
0x0000072a  ffff c400 0000 6cff ffff e400 0000 dcff  ......l.........
0x0000073a  ffff 2c01 0000 1400 0000 0000 0000 017a  ..,............z
[0x0000064a]> px ~$!
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x0000073a  ffff 2c01 0000 1400 0000 0000 0000 017a  ..,............z
0x0000072a  ffff c400 0000 6cff ffff e400 0000 dcff  ......l.........
0x0000071a  ffff ac00 0000 3cfe ffff 5400 0000 46ff  ......<...T...F.
0x0000070a  0000 0600 0000 0cfe ffff 8400 0000 2cfe  ..............,.
0x000006fa  2052 6164 6172 6532 2100 011b 033b 3800   Radare2!....;8.
0x000006ea  c408 c300 0000 0100 0200 4865 6c6c 6f2c  ..........Hello,
0x000006da  8400 0000 0000 f3c3 0000 4883 ec08 4883  ..........H...H.
0x000006ca  5b5d 415c 415d 415e 415f c390 662e 0f1f  []A\A]A^A_..f...
0x000006ba  ff14 dc48 83c3 0148 39dd 75ea 4883 c408  ...H...H9.u.H...
0x000006aa  8400 0000 0000 4c89 fa4c 89f6 4489 ef41  ......L..L..D..A
0x0000069a  fd03 e84f feff ff48 85ed 7420 31db 0f1f  ...O...H..t 1...
0x0000068a  5341 89fd 4989 f64c 29e5 4883 ec08 48c1  SA..I..L).H...H.
0x0000067a  544c 8d25 3607 2000 5548 8d2d 3607 2000  TL.%6. .UH.-6. .
0x0000066a  8400 0000 0000 4157 4156 4989 d741 5541  ......AWAVI..AUA
0x0000065a  e8c1 feff ffb8 0000 0000 5dc3 662e 0f1f  ..........].f...
0x0000064a  5548 89e5 488d 3d9f 0000 00b8 0000 0000  UH..H.=.........

+는 대소문자를 구분하지 않고 결과를 출력합니다. ^는 각 라인에 가장 처음을 의미하고 $은 각라인의 끝을 의미합니다. 정규표현식의 그것과 동일합니다. ??.은 일치하는 줄이나 문자의 개수를 출력합니다. :s..e는 결과중 s번째 라인부터 e번째 라인까지 출력하는 수식어입니다. .....은 내장 lesshud입니다.

마지막으로 ~의 가장 중요한 것은 column기능입니다. column기능을 사용하면 손쉽게 원하는 부분을 찾아서 바로바로 명령어에 사용할 수 있습니다. 예를 들어서 main으로 커서를 옮길때 처음에 사용했던것처럼 사용해도 되지만 다음과 같이 바로 찾아갈 수 있습니다.


[0x00000540]> s `afl ~sym.main[0]`

@은 임시적으로 커서를 지정할 때 사용하는 수식어 입니다. 예를 들어서 특정 주소를 디스어셈블링해야 되거나 메모리의 내용을 확인해야 될때 @를 사용해서 확인을 할 수 있습니다. 예를 들어서 다음과 같이 사용할 수 있습니다. @에 아무것도 오지 않을 경우 현재 커서를 의미합니다. 주소 뒤에 ! 붙혀서 사이즈를 조정할 수 있습니다.


[0x00000000]> pdf @ 0x64a
            ;-- main:
/ (fcn) sym.main 28
|   sym.main (int argc, char **argv, char **envp);
|           ; DATA XREF from entry0 (0x55d)
|           0x0000064a      55             push rbp
|           0x0000064b      4889e5         mov rbp, rsp
|           0x0000064e      488d3d9f0000.  lea rdi, str.Hello__Radare2 ; 0x6f4 ; "Hello, Radare2!" ; const char *format
|           0x00000655      b800000000     mov eax, 0
|           0x0000065a      e8c1feffff     call sym.imp.printf         ; int printf(const char *format)
|           0x0000065f      b800000000     mov eax, 0
|           0x00000664      5d             pop rbp
\           0x00000665      c3             ret

[0x00000000]> pd @ 0x64a!2
            ;-- main:
/ (fcn) sym.main 28
|   sym.main (int argc, char **argv, char **envp);
|           ; DATA XREF from entry0 (0x55d)
|           0x0000064a      55             push rbp
|           0x0000064b      4889e5         mov rbp, rsp

|>pipe은 유닉스 쉘에서 사용되는 파이프와 동일합니다. 물론 여기에서는 내부 명령어가 아니라 쉘 명령어로 파이프가 작동합니다.


Expressions

r2는 자체적인 계산기능을 지원하며 ?를 통해 확인할 수 있습니다. 지원하는 연산자는 다음과 같으며 변수는 ?$?를 통해 확인할 수 있습니다. 변수와 관련해서는 나중에 자세히 서술하겠습니다.

  • +
  • -
  • *
  • /
  • %
  • >
  • <
  • |
  • &
  • ^

|을 사용하여 or연산을 할때는 ""으로 묶어줘야지 파이프로 해석을 안하고 수식으로 해석합니다.

먼저 ?만 가지고 수식을 계산할 경우 모든 형식에 대한 결과를 보여줍니다.


[0x00000000]> ? 1+1
hex     0x2
octal   02
unit    2
segment 0000:0002
int32   2
string  "\x02"
binary  0b00000010
fvalue: 2.0
float:  0.000000f
double: 0.000000
trits   0t2

?vi를 사용할 경우 정수로 결과를 표시합니다. ?vi뒤에 1, 2, 4, 8를 붙힐 수 있는데 숫자를 붙힐 경우 해당하는 바이트 수 만큼만 출력을 하거나 오버플로우를 적용해서 보여줍니다. 예를 들어서 다음과 같습니다.


[0x00000000]> ?vx 2147483647
0x7fffffff
[0x00000000]> ?vi1 2147483647
-1
[0x00000000]> ?vi2 2147483647
-1
[0x00000000]> ?vi4 2147483647
2147483647
[0x00000000]> ?vi8 2147483647
2147483647
h4n9u1

h4n9u1
Back-End Developer and Newbie Linux System Administrator, Newbie Hacker(System, RE, Web)