mirror of
https://github.com/radareorg/radare2.git
synced 2024-10-07 10:33:30 +00:00
* Apply whats's patch fixing r_search for stripstr
- Thanks! :) * Added dummy r_socket_proc_* api - Needs to be moved outside r_socket - Added two non-working usage examples * Add some checks and enhacements to the r_buf API - Implemented in r_util.vapi * R_APIfy the r_cache api * Add missing methods in r_socket.vapi * Update the README file in r_anal describing the new design of r_anal..not yet finished
This commit is contained in:
parent
c67e0dec3d
commit
deb263a5fb
3
TODO
3
TODO
@ -6,6 +6,9 @@
|
||||
|
||||
----------------------------------------[ todo
|
||||
|
||||
* if we use objcopy --stripsymbols on a library..the stripped symbols are not
|
||||
listed by nm or rabin..but objcopy is able to see them O_O
|
||||
|
||||
* store version information in libraries ?
|
||||
* public delegate void RangeEachFunc(int i);
|
||||
* public void each(RangeEachFunc each_func) { ... }
|
||||
|
310
libr/anal/README
310
libr/anal/README
@ -4,9 +4,11 @@ Code analysis module
|
||||
* TODO: Add static plugin support here
|
||||
|
||||
Analysis an = new Analysis ();
|
||||
io.bind (an);
|
||||
an.set ("x86");
|
||||
an.set_bytes (buf, 1024);
|
||||
an.analyze ();
|
||||
var ctx = new Analysis.Context(an);
|
||||
//ctx.set_bytes (0x8048000, buf, 1024); // this must be a callback
|
||||
ctx.analyze (0x8048300);
|
||||
var foo = an.get_function_preludes ();
|
||||
var calls = an.get_calls ();
|
||||
foreach var (calls) {
|
||||
@ -15,3 +17,307 @@ foreach var (calls) {
|
||||
stdout.printf("arg%d: %s\n" i, var.arg[i]);
|
||||
}
|
||||
}
|
||||
an.accept(ctx);
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
Global picture
|
||||
|
||||
(anal) -> can keep track of results of different context (functions ...)
|
||||
|
|
||||
`---> we get a context.. so we work there with
|
||||
(anal context owns stack, regs, ...)
|
||||
- able to detect function arguments
|
||||
- we can configure the context in a way or other
|
||||
- it is able to get info from global anal
|
||||
- feeded with bytes
|
||||
|
||||
r_anal_get_bb(an, 0x804800);
|
||||
r_anal_op_t * op = r_anal_get_op(an, 0x804800);
|
||||
r_anal_get_fun(an, 0x804800);
|
||||
|
||||
void analyze_graph(Analysis an, uint64 addr)
|
||||
{
|
||||
var? op = an.get_op(addr);
|
||||
while (op != null) {
|
||||
if (op.type == Analysis.OpcodeType.BRANCH) {
|
||||
foreach (var jmp in op.refs) {
|
||||
if (jmp.type | Analysis.AccessType.EXEC)
|
||||
print("0x%08llx : branch 0x%08llx\n", op.addr, jmp.addr);
|
||||
analyze_graph(an, jmp.addr);
|
||||
}
|
||||
}
|
||||
op = op.next();
|
||||
}
|
||||
}
|
||||
|
||||
void analyze_function(Analysis an, uint64 addr)
|
||||
{
|
||||
Analysis.Function? fun = an.get_fun(addr);
|
||||
if (fun == null)
|
||||
Log.err("No function found at address 0x%08llx".printf());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
----------------------------------------
|
||||
|
||||
// Must use r_alloc_pool for every type of structure (per function level)
|
||||
// Must store all this info using r_db
|
||||
// Only index when requested (tempral analysis are temporal)
|
||||
// Do we have to enable jump/call toggles for breaking basicblocks?
|
||||
// Memory selectors are just modifiers .. how?
|
||||
// How to handle with self-modifying code?
|
||||
- if its a conditional branch, refs are true , false
|
||||
- if not and there is more than one branch is all the possibilities
|
||||
- if an address is accessed in read|write and exec mode we should warn!
|
||||
xrefs[] = {
|
||||
addr = 0x8048480
|
||||
type = R|W|X - executable xrefs are control flow branches,
|
||||
- read/write are for data
|
||||
}
|
||||
refs[] = {
|
||||
op = eq,add,mul ??
|
||||
reg = regidx
|
||||
addr = 0x8048580
|
||||
type = R|W|X
|
||||
}
|
||||
|
||||
// we need an api in r_buf to modify bits with endian and values..
|
||||
struct bin {
|
||||
int offset;
|
||||
int size;
|
||||
int endian;
|
||||
};
|
||||
|
||||
enum type {
|
||||
IMM
|
||||
REG
|
||||
MEM
|
||||
};
|
||||
|
||||
struct r_anal_value_t {
|
||||
int op; // NOP, ADD, SEL, ...
|
||||
int type; // opcode, reg, imm, addr
|
||||
ut64 num; // idxofreg, immvalue, addrnum
|
||||
struct bin bin;
|
||||
int size;
|
||||
int nextop; // ADD, MUL, ...
|
||||
struct r_anal_value_t *next;
|
||||
};
|
||||
|
||||
struct arg {
|
||||
int rw; // READ | WRITE direction
|
||||
int nv; // number of values
|
||||
struct r_anal_value_t *v;
|
||||
};
|
||||
|
||||
mov eax, [0x8048+eax*4]
|
||||
|
||||
mov -> args = { "eax", {0x8048 {+eax*4}} }
|
||||
|
||||
struct r_anal_ref_t {
|
||||
int type; // READ, WRITE, EXEC
|
||||
struct r_anal_value_t value;
|
||||
};
|
||||
|
||||
struct r_anal_op_t {
|
||||
ut64 addr;
|
||||
int frame;
|
||||
int type;
|
||||
int cond;
|
||||
int nestlevel;
|
||||
int length;
|
||||
int crc;
|
||||
struct r_anal_value_t rep;
|
||||
int nargs;
|
||||
struct arg args[];
|
||||
|
||||
struct r_anal_op_t *next;
|
||||
int nrefs;
|
||||
struct r_anal_ref_t refs[];
|
||||
int nxrefs;
|
||||
struct r_anal_ref_t xrefs[];
|
||||
};
|
||||
|
||||
/* basic block */
|
||||
struct r_anal_bb_t {
|
||||
ut64 addr;
|
||||
int type;
|
||||
int size;
|
||||
ut8 *bytes;
|
||||
struct r_anal_op_t *head; // opcode heading this basic block
|
||||
struct r_anal_ref_t refs[];
|
||||
struct r_anal_ref_t xrefs[];
|
||||
};
|
||||
|
||||
/* function */
|
||||
struct r_anal_fun_t {
|
||||
char *name;
|
||||
ut64 addr;
|
||||
int size;
|
||||
// XXX: use r_ranges instead of addr+size?
|
||||
struct r_anal_ref_t refs[];
|
||||
struct r_anal_ref_t xrefs[];
|
||||
};
|
||||
|
||||
/* used to emulate */
|
||||
struct r_anal_arch_t {
|
||||
struct r_reg_t reg;
|
||||
char **regs;
|
||||
int pc; // program counter
|
||||
int sp; // stack pointer
|
||||
int bp; // base pointer
|
||||
int gp; // global pointer
|
||||
int sr; // src
|
||||
int dr; // dst
|
||||
};
|
||||
|
||||
const char **regs = { "eax", "ebx", "ecx", "...", NULL };
|
||||
|
||||
if (opcode.xrefs[i].type & R_ANAL_XS_EXEC)
|
||||
|
||||
// compilation process defines a mapping between the binary representation
|
||||
// of an opcode into an AST of structs describing the opcode itself or
|
||||
// we can just serialize it into a evaluable string
|
||||
// - evaluable strings are cheaper in memory consumption
|
||||
// - strstr(es, "%eax") easy way to check if a register is used
|
||||
// - the eval string should be converted into an AST at some point
|
||||
|
||||
Analysis levels:
|
||||
================
|
||||
- opcode level
|
||||
- frame size
|
||||
- conditional (used by branches(jumps) and arm opcodes)
|
||||
- weight (importance) (if <0, it is a nop) trash detection
|
||||
- XXX file/line (dwarf nfo??? here) i think no
|
||||
- lifetime of register value (detect if
|
||||
- nesting level (branch analysis)
|
||||
- sign
|
||||
- type
|
||||
-- operand level:
|
||||
- bitsize
|
||||
- mem | reg | imm
|
||||
- value
|
||||
- direction (read|write)
|
||||
- operand index
|
||||
- basic block level
|
||||
- bytes + length + (checksum?)
|
||||
- type (head, tail, body, last)
|
||||
- xrefs (branches to here)
|
||||
- refs (must be an array)
|
||||
- true branch
|
||||
- false branch
|
||||
- destinations[] // for call eax and so
|
||||
- function level
|
||||
- name
|
||||
- offset range (r_range here, functions do not need to be linear)
|
||||
- variables (use r_var) (( merge r_var here? ))
|
||||
- arguments ("")
|
||||
- xrefs
|
||||
- calls (outrefs)
|
||||
== graph simplification (serialize blocks with direct branches (jmp))
|
||||
- program
|
||||
- comprends data + code trees
|
||||
- all references must be stored twice
|
||||
- r_range of functions, data and other shit
|
||||
|
||||
Context analysis:
|
||||
=================
|
||||
- Merge r_vm here -- multiarchitecture code emulation
|
||||
- Allows to track register lifetime,
|
||||
- Detect possible values for 'call eax' f.ex
|
||||
- Identify fake conditional branches
|
||||
|
||||
TEH RIR
|
||||
=======
|
||||
The radare intermediate representation.
|
||||
- ascii representation of opcode level analysis
|
||||
|
||||
-- epilog/prolog bytez for extra function detection
|
||||
|
||||
Architecture language
|
||||
=====================
|
||||
Allows to describe an architecture (byte parsing, read/write)
|
||||
- opcode reassembling
|
||||
- automatic code analysis
|
||||
r_anal_opcode_set(op, R_OPTYPE_ADD);
|
||||
- opcode level analysis can be manually modified in runtime
|
||||
- basic blocks can change
|
||||
|
||||
Decompilation
|
||||
=============
|
||||
Use ALT .. in a inverse way OMG thats freaking
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
opcode_analyze ()
|
||||
- parse bytes and fill an structure
|
||||
- opcode type and arguments
|
||||
- underlying vm code
|
||||
opcode_modify ()
|
||||
- modify the bytes based on the structure changes
|
||||
- the structure should expose the bit level info to make this possible
|
||||
// this is //
|
||||
* modify reg, immediate or memory values
|
||||
|
||||
+--------------+
|
||||
| AnalArchLang | **
|
||||
+--------------+
|
||||
if [arg0 == 0xff] {
|
||||
reg = { eax, ecx, edx, ebx, esp, ebp, esi, edi }
|
||||
jmp [0xe0+reg]
|
||||
jmp [0xe8+reg]
|
||||
|
||||
reg = { eax, ecx, edx, ebx, esp, ebp, esi, edi }
|
||||
push [0xf0+reg]
|
||||
|
||||
reg = { eax, ecx, edx, ebx, esp, ebp, esi, edi }
|
||||
call [0xd0+reg]
|
||||
call [0xd8+reg]
|
||||
}
|
||||
|
||||
[0:7]=e8 {
|
||||
type = "call"
|
||||
addr = [8:31]
|
||||
len = 5
|
||||
}
|
||||
[0:7]=50 && [0:7]<60 {
|
||||
type = "push"
|
||||
len = 1
|
||||
}
|
||||
[0:7]=c3 {
|
||||
type = "ret"
|
||||
len = 1
|
||||
}
|
||||
|
||||
BASIC OPS we need for the IR
|
||||
============================ -- this is RISC! :D
|
||||
|
||||
Each opcode must support a size value. The format is:
|
||||
We need some intermediate temporal registers
|
||||
|
||||
|
||||
lispy assembly:
|
||||
(addi eax 3)
|
||||
(addi *(+ eax 8) 3)
|
||||
|
||||
lea edi, [ecx*4-0x4]
|
||||
(set edi (- (* ecx 4) 4)
|
||||
(set edi (* ecx 4 - 4)) ; iterative format
|
||||
|
||||
1 byte 1 N N
|
||||
[ opcode ] [ type|size ] [ arg ] [ arg ]
|
||||
|
||||
type = [ op | reg | mem | imm ] ; 2 bits is enought
|
||||
size = 1, 2, 4, 8 ; byte level
|
||||
|
||||
ADD reg, reg
|
||||
SUB reg,
|
||||
JMP reg
|
||||
JMP imm
|
||||
JMP mem
|
||||
SET reg, imm
|
||||
STO mem, reg ; store register value into memory
|
||||
LOA reg, mem ; load memory value into register
|
||||
...
|
||||
|
@ -42,6 +42,7 @@ R_API int r_anal_add(struct r_anal_t *anal, struct r_anal_handle_t *foo)
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
// TODO: Must be deprecated
|
||||
R_API int r_anal_list(struct r_anal_t *anal)
|
||||
{
|
||||
struct list_head *pos;
|
||||
@ -52,7 +53,7 @@ R_API int r_anal_list(struct r_anal_t *anal)
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
R_API int r_anal_set(struct r_anal_t *anal, const char *name)
|
||||
R_API int r_anal_use(struct r_anal_t *anal, const char *name)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &anal->anals) {
|
||||
@ -164,6 +165,7 @@ R_API struct r_anal_refline_t *r_anal_reflines_get(struct r_anal_t *anal, ut8 *b
|
||||
/* umf..this should probably be outside this file*/
|
||||
R_API int r_anal_reflines_str(struct r_anal_t *anal, struct r_anal_refline_t *list, char *str, int opts)
|
||||
{
|
||||
struct r_anal_refline_t *ref;
|
||||
struct list_head *pos;
|
||||
int dir = 0;
|
||||
char ch = ' ';
|
||||
@ -178,8 +180,7 @@ R_API int r_anal_reflines_str(struct r_anal_t *anal, struct r_anal_refline_t *li
|
||||
|
||||
for (pos = linestyle?(&(list->list))->next:(&(list->list))->prev;
|
||||
pos != (&(list->list)); pos = linestyle?pos->next:pos->prev) {
|
||||
|
||||
struct r_anal_refline_t *ref = list_entry(pos, struct r_anal_refline_t, list);
|
||||
ref = list_entry(pos, struct r_anal_refline_t, list);
|
||||
|
||||
if (anal->pc == ref->to) dir = 1;
|
||||
// TODO: use else here
|
||||
|
@ -8,10 +8,11 @@ R_API void r_anal_ctx_init(struct r_anal_ctx_t *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
R_API struct r_anal_ctx_t *r_anal_ctx_new()
|
||||
R_API struct r_anal_ctx_t *r_anal_ctx_new(struct r_anal_t *anal)
|
||||
{
|
||||
struct r_anal_ctx_t *ctx = MALLOC_STRUCT(struct r_anal_ctx_t);
|
||||
r_anal_ctx_init(ctx);
|
||||
ctx->anal = anal;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -13,56 +13,56 @@
|
||||
#define R_ANAL_MAXREG 16
|
||||
|
||||
enum {
|
||||
R_ANAL_AOP_FAMILY_UNKNOWN = 0,
|
||||
R_ANAL_AOP_FAMILY_CPU, /* normal cpu insturction */
|
||||
R_ANAL_AOP_FAMILY_FPU, /* fpu (floating point) */
|
||||
R_ANAL_AOP_FAMILY_MMX, /* multimedia instruction (packed data) */
|
||||
R_ANAL_AOP_FAMILY_PRIV, /* priviledged instruction */
|
||||
R_ANAL_AOP_FAMILY_LAST
|
||||
R_ANAL_OP_FAMILY_UNKNOWN = 0,
|
||||
R_ANAL_OP_FAMILY_CPU, /* normal cpu insturction */
|
||||
R_ANAL_OP_FAMILY_FPU, /* fpu (floating point) */
|
||||
R_ANAL_OP_FAMILY_MMX, /* multimedia instruction (packed data) */
|
||||
R_ANAL_OP_FAMILY_PRIV, /* priviledged instruction */
|
||||
R_ANAL_OP_FAMILY_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
R_ANAL_AOP_TYPE_NULL = 0,
|
||||
R_ANAL_AOP_TYPE_JMP, /* mandatory jump */
|
||||
R_ANAL_AOP_TYPE_UJMP, /* unknown jump (register or so) */
|
||||
R_ANAL_AOP_TYPE_CJMP, /* conditional jump */
|
||||
R_ANAL_AOP_TYPE_CALL, /* call to subroutine (branch+link) */
|
||||
R_ANAL_AOP_TYPE_RCALL, /* call to register */
|
||||
R_ANAL_AOP_TYPE_REP, /* repeats next instruction N times */
|
||||
R_ANAL_AOP_TYPE_RET, /* returns from subrutine */
|
||||
R_ANAL_AOP_TYPE_ILL, /* illegal instruction // trap */
|
||||
R_ANAL_AOP_TYPE_UNK, /* unknown opcode type */
|
||||
R_ANAL_AOP_TYPE_NOP, /* does nothing */
|
||||
R_ANAL_AOP_TYPE_MOV, /* register move */
|
||||
R_ANAL_AOP_TYPE_TRAP, /* it's a trap! */
|
||||
R_ANAL_AOP_TYPE_SWI, /* syscall, software interrupt */
|
||||
R_ANAL_AOP_TYPE_UPUSH, /* unknown push of data into stack */
|
||||
R_ANAL_AOP_TYPE_PUSH, /* push value into stack */
|
||||
R_ANAL_AOP_TYPE_POP, /* pop value from stack to register */
|
||||
R_ANAL_AOP_TYPE_CMP, /* copmpare something */
|
||||
R_ANAL_AOP_TYPE_ADD,
|
||||
R_ANAL_AOP_TYPE_SUB,
|
||||
R_ANAL_AOP_TYPE_MUL,
|
||||
R_ANAL_AOP_TYPE_DIV,
|
||||
R_ANAL_AOP_TYPE_SHR,
|
||||
R_ANAL_AOP_TYPE_SHL,
|
||||
R_ANAL_AOP_TYPE_OR,
|
||||
R_ANAL_AOP_TYPE_AND,
|
||||
R_ANAL_AOP_TYPE_XOR,
|
||||
R_ANAL_AOP_TYPE_NOT,
|
||||
R_ANAL_AOP_TYPE_STORE, /* store from register to memory */
|
||||
R_ANAL_AOP_TYPE_LOAD, /* load from memory to register */
|
||||
R_ANAL_AOP_TYPE_LAST
|
||||
R_ANAL_OP_TYPE_NULL = 0,
|
||||
R_ANAL_OP_TYPE_JMP, /* mandatory jump */
|
||||
R_ANAL_OP_TYPE_UJMP, /* unknown jump (register or so) */
|
||||
R_ANAL_OP_TYPE_CJMP, /* conditional jump */
|
||||
R_ANAL_OP_TYPE_CALL, /* call to subroutine (branch+link) */
|
||||
R_ANAL_OP_TYPE_RCALL, /* call to register */
|
||||
R_ANAL_OP_TYPE_REP, /* repeats next instruction N times */
|
||||
R_ANAL_OP_TYPE_RET, /* returns from subrutine */
|
||||
R_ANAL_OP_TYPE_ILL, /* illegal instruction // trap */
|
||||
R_ANAL_OP_TYPE_UNK, /* unknown opcode type */
|
||||
R_ANAL_OP_TYPE_NOP, /* does nothing */
|
||||
R_ANAL_OP_TYPE_MOV, /* register move */
|
||||
R_ANAL_OP_TYPE_TRAP, /* it's a trap! */
|
||||
R_ANAL_OP_TYPE_SWI, /* syscall, software interrupt */
|
||||
R_ANAL_OP_TYPE_UPUSH, /* unknown push of data into stack */
|
||||
R_ANAL_OP_TYPE_PUSH, /* push value into stack */
|
||||
R_ANAL_OP_TYPE_POP, /* pop value from stack to register */
|
||||
R_ANAL_OP_TYPE_CMP, /* copmpare something */
|
||||
R_ANAL_OP_TYPE_ADD,
|
||||
R_ANAL_OP_TYPE_SUB,
|
||||
R_ANAL_OP_TYPE_MUL,
|
||||
R_ANAL_OP_TYPE_DIV,
|
||||
R_ANAL_OP_TYPE_SHR,
|
||||
R_ANAL_OP_TYPE_SHL,
|
||||
R_ANAL_OP_TYPE_OR,
|
||||
R_ANAL_OP_TYPE_AND,
|
||||
R_ANAL_OP_TYPE_XOR,
|
||||
R_ANAL_OP_TYPE_NOT,
|
||||
R_ANAL_OP_TYPE_STORE, /* store from register to memory */
|
||||
R_ANAL_OP_TYPE_LOAD, /* load from memory to register */
|
||||
R_ANAL_OP_TYPE_LAST
|
||||
};
|
||||
|
||||
/* TODO: what to do with signed/unsigned conditionals? */
|
||||
enum {
|
||||
R_ANAL_AOP_COND_EQ,
|
||||
R_ANAL_AOP_COND_NE,
|
||||
R_ANAL_AOP_COND_GE,
|
||||
R_ANAL_AOP_COND_GT,
|
||||
R_ANAL_AOP_COND_LE,
|
||||
R_ANAL_AOP_COND_LT,
|
||||
R_ANAL_OP_COND_EQ,
|
||||
R_ANAL_OP_COND_NE,
|
||||
R_ANAL_OP_COND_GE,
|
||||
R_ANAL_OP_COND_GT,
|
||||
R_ANAL_OP_COND_LE,
|
||||
R_ANAL_OP_COND_LT,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -125,22 +125,22 @@ struct r_anal_fcn_t {
|
||||
ut64 to;
|
||||
};
|
||||
|
||||
struct r_anal_t {
|
||||
int bits;
|
||||
int big_endian;
|
||||
ut64 pc;
|
||||
void *user;
|
||||
struct r_anal_handle_t *cur;
|
||||
struct list_head anals;
|
||||
};
|
||||
|
||||
struct r_anal_ctx_t {
|
||||
/* TODO: add more info here */
|
||||
/* per opcode deep level */
|
||||
/* per opcode stack size */
|
||||
/* basic blocks */
|
||||
int stacksize;
|
||||
};
|
||||
|
||||
struct r_anal_t {
|
||||
int bits;
|
||||
int big_endian;
|
||||
ut64 pc;
|
||||
void *user;
|
||||
struct r_anal_ctx_t *ctx;
|
||||
struct r_anal_handle_t *cur;
|
||||
struct list_head anals;
|
||||
struct r_anal_t *anal;
|
||||
};
|
||||
|
||||
struct r_anal_handle_t {
|
||||
@ -159,7 +159,7 @@ struct r_anal_t *r_anal_new();
|
||||
void r_anal_set_user_ptr(struct r_anal_t *anal, void *user);
|
||||
int r_anal_add(struct r_anal_t *anal, struct r_anal_handle_t *foo);
|
||||
int r_anal_list(struct r_anal_t *anal);
|
||||
int r_anal_set(struct r_anal_t *anal, const char *name);
|
||||
int r_anal_use(struct r_anal_t *anal, const char *name);
|
||||
int r_anal_set_bits(struct r_anal_t *anal, int bits);
|
||||
int r_anal_set_big_endian(struct r_anal_t *anal, int boolean);
|
||||
int r_anal_set_pc(struct r_anal_t *a, ut64 pc);
|
||||
|
@ -13,7 +13,6 @@
|
||||
#define CONS_MAX_USER 102400
|
||||
#define CONS_BUFSZ 0x4f00
|
||||
#define STR_IS_NULL(x) (!x || !x[0])
|
||||
#define IS_PRINTABLE(x) (x>=' '&&x<='~')
|
||||
|
||||
R_API void r_cons_break(void (*cb)(void *u), void *user);
|
||||
R_API void r_cons_break_end();
|
||||
|
@ -49,7 +49,7 @@ R_API struct r_reg_t *r_reg_init(struct r_reg_t *reg);
|
||||
R_API struct r_reg_t *r_reg_new();
|
||||
R_API int r_reg_set_profile_string(struct r_reg_t *reg, const char *profile);
|
||||
R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile);
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name);
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name, int type);
|
||||
R_API struct list_head *r_reg_get_list(struct r_reg_t *reg, int type);
|
||||
R_API int r_reg_type_by_name(const char *str);
|
||||
|
||||
|
@ -42,8 +42,8 @@ struct r_search_t {
|
||||
int n_kws;
|
||||
int mode;
|
||||
ut32 pattern_size;
|
||||
ut32 string_min;
|
||||
ut32 string_max;
|
||||
ut32 string_min; /* min number of matches */
|
||||
ut32 string_max; /* max number of matches */
|
||||
void *user; /* user data */
|
||||
int (*callback)(struct r_search_kw_t *kw, void *user, ut64 where);
|
||||
//struct r_search_binparse_t *bp;
|
||||
@ -76,7 +76,7 @@ R_API int r_search_set_blocksize(struct r_search_t *s, ut32 bsize);
|
||||
// TODO: this is internal API?
|
||||
R_API int r_search_mybinparse_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len);
|
||||
R_API int r_search_aes_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len);
|
||||
R_API int r_search_strings_update_char(const unsigned char *buf, int min, int max, int enc, ut64 offset, const char *match);
|
||||
R_API int r_search_strings_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len, int enc);
|
||||
R_API int r_search_regexp_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len);
|
||||
R_API int r_search_xrefs_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len);
|
||||
|
||||
|
@ -3,6 +3,40 @@
|
||||
|
||||
#include "r_types.h"
|
||||
|
||||
/* TODO: major refactoring of r_socket */
|
||||
/* make it work like the rest of apis */
|
||||
/* struct r_socket_t *sock = r_socket_new(R_SOCKET_TCP, "gogle.com", 80); */
|
||||
/* struct r_socket_t *sock = r_socket_proc_new(R_SOCKET_PROCESS, "/bin/ls", 80); */
|
||||
|
||||
/* process */
|
||||
|
||||
struct r_socket_proc_t {
|
||||
int fd0[2];
|
||||
int fd1[2];
|
||||
int pid;
|
||||
};
|
||||
|
||||
R_API struct r_socket_proc_t *r_socket_proc_open(char *const argv[]);
|
||||
R_API int r_socket_proc_close(struct r_socket_proc_t *sp);
|
||||
#define r_socket_proc_read(x,y,z) r_socket_read(x->fd1[0],y,z)
|
||||
#define r_socket_proc_fgets(x,y,z) r_socket_fgets(x->fd1[0],y,z)
|
||||
#define r_socket_proc_write(x,y,z) r_socket_write(x->fd0[1],y,z)
|
||||
#define r_socket_proc_printf(x,y) r_socket_printf(x->fd0[1],y)
|
||||
#define r_socket_proc_ready(x,y,z) r_socket_ready(x->fd1[0],y,z)
|
||||
|
||||
// read from stdout of process is fd1[0]
|
||||
// write to stdin of process is fd0[1]
|
||||
|
||||
|
||||
/* socket */
|
||||
|
||||
#if __UNIX__
|
||||
R_API int r_socket_unix_connect(const char *file);
|
||||
R_API int r_socket_unix_listen(const char *file);
|
||||
#endif
|
||||
|
||||
R_API int r_socket_flush(int fd);
|
||||
R_API void r_socket_block(int fd, int block);
|
||||
R_API int r_socket_ready(int fd, int secs, int usecs);
|
||||
R_API int r_socket_read(int fd, unsigned char *read, int len);
|
||||
R_API int r_socket_write(int fd, unsigned char *buf, int len);
|
||||
|
@ -73,7 +73,7 @@ static inline int ERR(char *str, ...)
|
||||
#define MALLOC_STRUCTS(x,y) (x*)malloc(sizeof(x)*y)
|
||||
#define MALLOC_STRUCT(x) (x*)malloc(sizeof(x))
|
||||
#define IS_PRINTABLE(x) (x>=' '&&x<='~')
|
||||
#define IS_WHITESPACE(x) (x==' '&&x=='\t')
|
||||
#define IS_WHITESPACE(x) (x==' '||x=='\t')
|
||||
|
||||
/* operating system */
|
||||
|
||||
|
@ -22,6 +22,7 @@ R_API struct r_mem_pool_t* r_mem_pool_init(struct r_mem_pool_t *pool, int nodesi
|
||||
R_API struct r_mem_pool_t *r_mem_pool_new(int nodesize, int poolsize, int poolcount);
|
||||
R_API struct r_mem_pool_t *r_mem_pool_free(struct r_mem_pool_t *pool);
|
||||
R_API void* r_mem_pool_alloc(struct r_mem_pool_t *pool);
|
||||
R_API int r_mem_count(ut8 **addr);
|
||||
|
||||
/* buf */
|
||||
struct r_buf_t {
|
||||
@ -30,6 +31,14 @@ struct r_buf_t {
|
||||
ut64 base;
|
||||
};
|
||||
|
||||
R_API struct r_buf_t *r_buf_init(struct r_buf_t *b);
|
||||
R_API struct r_buf_t *r_buf_new();
|
||||
R_API int r_buf_set_bits(struct r_buf_t *b, int bitoff, int bitsize, ut64 value);
|
||||
R_API int r_buf_set_bytes(struct r_buf_t *b, ut8 *buf, int length);
|
||||
R_API int r_buf_read_at(struct r_buf_t *b, ut64 addr, ut8 *buf, int len);
|
||||
R_API int r_buf_write_at(struct r_buf_t *b, ut64 addr, const ut8 *buf, int len);
|
||||
R_API void r_buf_free(struct r_buf_t *b);
|
||||
|
||||
/* r_cache */
|
||||
// TOTHINK: move into a separated library?
|
||||
struct r_cache_item_t {
|
||||
@ -155,4 +164,5 @@ R_API const char *r_sys_getenv(const char *key);
|
||||
R_API int r_sys_setenv(const char *key, const char *value, int ow);
|
||||
R_API char *r_sys_cmd_str(const char *cmd, const char *input, int *len);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -21,3 +21,7 @@ and virtual analysis
|
||||
|
||||
TODO:
|
||||
- add support for sign/unsigned registers..or at least a way to cast them
|
||||
- add push/pop of register states (maybe we only need 2 levels of states)
|
||||
- can be used for diffing registers
|
||||
- is also useful to store values before emulating code
|
||||
- we can probably implement this in a clone() method? (too heavy? more orgtogonal)
|
||||
|
@ -195,13 +195,21 @@ R_API int r_reg_set_profile(struct r_reg_t *reg, const char *profile)
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name)
|
||||
R_API struct r_reg_item_t *r_reg_get(struct r_reg_t *reg, const char *name, int type)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct r_reg_item_t *r;
|
||||
int i;
|
||||
int i, e;
|
||||
|
||||
for(i=0;i<R_REG_TYPE_LAST;i++) {
|
||||
if (type == -1) {
|
||||
i = 0;
|
||||
e = R_REG_TYPE_LAST;
|
||||
} else {
|
||||
i = type;
|
||||
e = type+1;
|
||||
}
|
||||
|
||||
for(;i<e;i++) {
|
||||
list_for_each(pos, ®->regset[i].regs) {
|
||||
r = list_entry(pos, struct r_reg_item_t, list);
|
||||
if (!strcmp(r->name, name))
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <r_util.h>
|
||||
|
||||
/* XXX: reg get can be accessed using the print_format stuff */
|
||||
// This is the same as r_buf_set_bits, arenas can be r_buf
|
||||
R_API ut64 r_reg_get_value(struct r_reg_t *reg, struct r_reg_item_t *item)
|
||||
{
|
||||
struct r_reg_set_t *regset;
|
||||
|
@ -137,7 +137,7 @@ R_API int r_search_set_callback(struct r_search_t *s, int (*callback)(struct r_s
|
||||
/* TODO: initialize update callback in _init */
|
||||
R_API int r_search_update(struct r_search_t *s, ut64 *from, const ut8 *buf, long len)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
switch(s->mode) {
|
||||
case R_SEARCH_KEYWORD:
|
||||
ret += r_search_mybinparse_update(s, *from, buf, len);
|
||||
@ -153,8 +153,7 @@ R_API int r_search_update(struct r_search_t *s, ut64 *from, const ut8 *buf, long
|
||||
*from -= R_SEARCH_AES_BOX_SIZE;
|
||||
break;
|
||||
case R_SEARCH_STRING:
|
||||
for(i=0;i<len;i++)
|
||||
ret += r_search_strings_update_char(buf+i, s->string_min, s->string_max, 0, *(from) +i/*enc*/, "");
|
||||
ret += r_search_strings_update(s, *from, buf, len, 0);
|
||||
break;
|
||||
case R_SEARCH_PATTERN:
|
||||
//ret += r_search_pattern_update(buf, s->pattern_size
|
||||
|
@ -54,27 +54,60 @@ static int is_encoded(int encoding, unsigned char c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX last char is lost :(
|
||||
R_API int r_search_strings_update_char(const ut8 *buf, int min, int max, int enc, ut64 offset, const char *match)
|
||||
R_API int r_search_strings_update(struct r_search_t *s, ut64 from, const ut8 *buf, int len, int enc)
|
||||
{
|
||||
int i = 0;
|
||||
static int widechar = 0;
|
||||
static int matches = 0;
|
||||
int widechar = 0;
|
||||
int matches = 0;
|
||||
char str[4096];
|
||||
|
||||
#define IS_PRINTABLE(x) (x>=' '&&x<='~')
|
||||
|
||||
if (IS_PRINTABLE(buf[i]) || (is_encoded(enc, buf[i]))) {
|
||||
for (i=0; i<len; i++) {
|
||||
char ch = buf[i];
|
||||
if (IS_PRINTABLE(ch) || IS_WHITESPACE(ch) || is_encoded(enc, ch)) {
|
||||
str[matches] = ch;
|
||||
if (matches < sizeof(str))
|
||||
matches++;
|
||||
} else {
|
||||
/* wide char check \x??\x00\x??\x00 */
|
||||
if (matches && buf[i+2]=='\0' && buf[i]=='\0' && buf[i+1]!='\0') {
|
||||
widechar = 1;
|
||||
return 1; // widechar
|
||||
}
|
||||
/* check if the length fits on our request */
|
||||
if (matches >= s->string_min && (s->string_max == 0 || matches <= s->string_max)) {
|
||||
str[matches] = '\0';
|
||||
int len = strlen(str);
|
||||
if (len>2) {
|
||||
if (widechar) {
|
||||
ut64 off = (ut64)from+i-(len*2)+1;
|
||||
printf("0x%08llx %3d W %s\n", off, len, str);
|
||||
} else {
|
||||
ut64 off = (ut64)from+i-matches;
|
||||
printf("0x%08llx %3d A %s\n", off, len, str);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
matches = 0;
|
||||
widechar = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
if (matches == 0)
|
||||
offset += i;
|
||||
#endif
|
||||
str[matches] = buf[i];
|
||||
R_API int r_search_strings_update_char(const ut8 *buf, int min, int max, int enc, ut64 offset, const char *match)
|
||||
{
|
||||
static int widechar = 0;
|
||||
static int matches = 0;
|
||||
static char str[4096];
|
||||
|
||||
if (IS_PRINTABLE(buf[0]) || is_encoded(enc, buf[0])) {
|
||||
str[matches] = buf[0];
|
||||
if (matches < sizeof(str))
|
||||
matches++;
|
||||
} else {
|
||||
/* wide char check \x??\x00\x??\x00 */
|
||||
if (matches && buf[i+2]=='\0' && buf[i]=='\0' && buf[i+1]!='\0') {
|
||||
if (matches && buf[2]=='\0' && buf[0]=='\0' && buf[1]!='\0') {
|
||||
widechar = 1;
|
||||
return 1; // widechar
|
||||
}
|
||||
@ -108,30 +141,21 @@ R_API int r_search_strings_update_char(const ut8 *buf, int min, int max, int enc
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// XXX THIS IS UGLY AS SHIT
|
||||
do {
|
||||
flag = flag_get(msg);
|
||||
if (flag && flag->offset != (offset-matches))
|
||||
strcat(msg, "0");
|
||||
else break;
|
||||
} while(1);
|
||||
#endif
|
||||
|
||||
printf("f %s @ 0x%08x\n", msg, (unsigned int)offset-matches);
|
||||
} else
|
||||
if ((!match) || (match && strstr(str, match)) ){
|
||||
int len = strlen(str);
|
||||
if (len>2) {
|
||||
if (widechar) {
|
||||
ut64 off = offset-(len*2)+1;
|
||||
printf("0x%08llx %3d W %s\n", off, len, str);
|
||||
} else {
|
||||
printf("0x%08llx %3d A %s\n",
|
||||
(ut64)offset-matches, len, str); //-matches, len, str);
|
||||
} else {
|
||||
if ((!match) || (match && strstr(str, match)) ){
|
||||
int len = strlen(str);
|
||||
if (len>2) {
|
||||
if (widechar) {
|
||||
ut64 off = offset-(len*2)+1;
|
||||
printf("0x%08llx %3d W %s\n", off, len, str);
|
||||
} else {
|
||||
printf("0x%08llx %3d A %s\n",
|
||||
(ut64)offset-matches, len, str);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
matches = 0;
|
||||
@ -139,6 +163,7 @@ R_API int r_search_strings_update_char(const ut8 *buf, int min, int max, int enc
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
int stripstr_from_file(const char *filename, int min, int max, int encoding, ut64 seek, ut64 limit)
|
||||
|
@ -1,10 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
#if 0
|
||||
TODO:
|
||||
support for multiple keywords
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
@ -22,16 +17,21 @@ static int fd = -1;
|
||||
static int rad = 0;
|
||||
struct r_search_t *rs;
|
||||
static ut64 from = 0LL, to = -1;
|
||||
static char *str;
|
||||
static char *mask = "";
|
||||
static int nonstop = 0;
|
||||
static int mode = R_SEARCH_KEYWORD;
|
||||
static int mode = R_SEARCH_STRING;
|
||||
static ut64 cur = 0;
|
||||
static ut8 *buffer = NULL;
|
||||
static char *curfile = NULL;
|
||||
static ut64 bsize = 4096;
|
||||
static int hexstr = 0;
|
||||
static struct r_print_t *pr = NULL;
|
||||
LIST_HEAD(kws_head);
|
||||
|
||||
struct str_t {
|
||||
char *str;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static int hit(struct r_search_kw_t *kw, void *user, ut64 addr) {
|
||||
//const ut8 *buf = (ut8*)user;
|
||||
@ -39,6 +39,7 @@ static int hit(struct r_search_kw_t *kw, void *user, ut64 addr) {
|
||||
if (rad) {
|
||||
printf("f hit%d_%d 0x%08llx ; %s\n", 0, kw->count, addr, curfile);
|
||||
} else {
|
||||
if (!kw->count) printf("; %s\n", kw->keyword);
|
||||
printf("%s: %03d @ 0x%llx\n", curfile, kw->count, addr);
|
||||
if (pr) {
|
||||
r_print_hexdump(pr, addr, (ut8*)buffer+delta, 78, 16, R_TRUE);
|
||||
@ -49,27 +50,31 @@ static int hit(struct r_search_kw_t *kw, void *user, ut64 addr) {
|
||||
}
|
||||
|
||||
static int show_help(char *argv0, int line) {
|
||||
printf("Usage: %s [-Xnzh] [-f from] [-t to] [-s str] [-z] [-x hex] file ...\n", argv0);
|
||||
printf("Usage: %s [-Xnzh] [-f from] [-t to] [-z] [-s str] [-x hex] file ...\n", argv0);
|
||||
if (line) return 0;
|
||||
printf(
|
||||
" -z search for zero-terminated strings\n"
|
||||
" -s [str] search for zero-terminated strings\n"
|
||||
" -x [hex] search for hexpair string (909090)\n"
|
||||
" -s [str] search for zero-terminated strings (can be used multiple times)\n"
|
||||
" -m [str] set a mask\n"
|
||||
" -x [hex] search for hexpair string (909090) (can be used multiple times)\n"
|
||||
" -f [from] start searching from address 'from'\n"
|
||||
" -f [to] stop search at address 'to'\n"
|
||||
" -X show hexdump of search results\n"
|
||||
" -n do not stop on read errors\n"
|
||||
" -r print using radare commands\n"
|
||||
" -b set block size\n"
|
||||
" -h show this help\n"
|
||||
" -V print version and exit\n"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radiff_open(char *file)
|
||||
int rafind_open(char *file)
|
||||
{
|
||||
int ret, last = 0;
|
||||
|
||||
struct list_head *pos;
|
||||
r_io_init(&io);
|
||||
// TODO: add support for multiple files
|
||||
|
||||
fd = r_io_open(&io, file, R_IO_READ, 0);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Cannot open file '%s'\n", file);
|
||||
@ -84,9 +89,13 @@ int radiff_open(char *file)
|
||||
to = r_io_size(&io, fd);
|
||||
}
|
||||
if (mode == R_SEARCH_KEYWORD) {
|
||||
if (hexstr)
|
||||
r_search_kw_add_hex(rs, str, mask);
|
||||
else r_search_kw_add(rs, str, mask);
|
||||
list_for_each(pos, &(kws_head)) {
|
||||
struct str_t *kw = list_entry(pos, struct str_t, list);
|
||||
if (hexstr)
|
||||
r_search_kw_add_hex(rs, kw->str, mask);
|
||||
else r_search_kw_add(rs, kw->str, mask);
|
||||
free(kw);
|
||||
}
|
||||
}
|
||||
curfile = file;
|
||||
r_search_begin(rs);
|
||||
@ -115,7 +124,10 @@ int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "s:x:Xzf:t:rnhV")) != -1) {
|
||||
while ((c = getopt(argc, argv, "b:m:s:x:Xzf:t:rnhV")) != -1) {
|
||||
struct str_t *kw = MALLOC_STRUCT(struct str_t);
|
||||
INIT_LIST_HEAD(&(kw->list));
|
||||
|
||||
switch(c) {
|
||||
case 'r':
|
||||
rad = 1;
|
||||
@ -125,8 +137,9 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 's':
|
||||
mode = R_SEARCH_KEYWORD;
|
||||
str = optarg;
|
||||
hexstr = 0;
|
||||
kw->str = optarg;
|
||||
list_add(&(kw->list), &(kws_head));
|
||||
break;
|
||||
case 'b':
|
||||
bsize = r_num_math(NULL, optarg);
|
||||
@ -137,7 +150,8 @@ int main(int argc, char **argv)
|
||||
case 'x':
|
||||
mode = R_SEARCH_KEYWORD;
|
||||
hexstr = 1;
|
||||
str = optarg;
|
||||
kw->str = optarg;
|
||||
list_add(&(kw->list), &(kws_head));
|
||||
break;
|
||||
case 'm':
|
||||
// XXX should be from hexbin
|
||||
@ -164,7 +178,7 @@ int main(int argc, char **argv)
|
||||
return show_help(argv[0], 1);
|
||||
|
||||
for (;optind < argc;optind++)
|
||||
radiff_open(argv[optind]);
|
||||
rafind_open(argv[optind]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
NAME=r_socket
|
||||
OBJ=socket.o
|
||||
OBJ=socket.o proc.o
|
||||
# on solaris only
|
||||
#LINK=-lsocket
|
||||
#LINK=-L../cons -lr_cons -Wl,-R../cons
|
||||
|
62
libr/socket/proc.c
Normal file
62
libr/socket/proc.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* XXX : move to r_util??? rename method names.. to long? */
|
||||
/* proc IO is not related to socket io.. this is shitty!! */
|
||||
|
||||
#include <r_socket.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if __UNIX__
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
R_API struct r_socket_proc_t *r_socket_proc_open(char *const argv[])
|
||||
{
|
||||
#if __UNIX__
|
||||
struct r_socket_proc_t *sp = MALLOC_STRUCT(struct r_socket_proc_t);
|
||||
int flags = O_CLOEXEC; //O_NONBLOCK|O_CLOEXEC;
|
||||
|
||||
if (pipe2(sp->fd0, flags)==-1) {
|
||||
perror("pipe");
|
||||
free(sp);
|
||||
return NULL;
|
||||
}
|
||||
if (pipe2(sp->fd1, flags)==-1) {
|
||||
perror("pipe");
|
||||
free(sp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sp->pid = fork();
|
||||
switch(sp->pid) {
|
||||
case 0:
|
||||
close(0);
|
||||
dup2(sp->fd0[0], 0);
|
||||
close(1);
|
||||
dup2(sp->fd1[1], 1);
|
||||
execv(argv[0], argv);
|
||||
exit(1);
|
||||
case -1:
|
||||
perror("fork");
|
||||
r_socket_proc_close(sp);
|
||||
free(sp);
|
||||
break;
|
||||
//r_socket_block(sp, R_FALSE);
|
||||
}
|
||||
return sp;
|
||||
#endif
|
||||
}
|
||||
|
||||
R_API int r_socket_proc_close(struct r_socket_proc_t *sp)
|
||||
{
|
||||
#if __UNIX__
|
||||
/* this is wrong */
|
||||
kill(sp->pid, 9);
|
||||
waitpid(sp->pid, NULL, 0); //WNOHANG);
|
||||
close(sp->fd0[0]);
|
||||
close(sp->fd0[1]);
|
||||
//close(sp->fd1[0]);
|
||||
close(sp->fd1[1]);
|
||||
//sp->fd[0] = -1;
|
||||
//sp->fd[1] = -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2006-2009 pancake<nopcode.org> */
|
||||
|
||||
#define USE_SOCKETS
|
||||
|
||||
#include <errno.h>
|
||||
@ -49,7 +50,7 @@ R_API int r_socket_write(int fd, unsigned char *buf, int len)
|
||||
// XXX: rewrite it to use select //
|
||||
/* waits secs until new data is received. */
|
||||
/* returns -1 on error, 0 is false, 1 is true */
|
||||
R_API int r_socket_ready(int fd, int secs,int usecs)
|
||||
R_API int r_socket_ready(int fd, int secs, int usecs)
|
||||
{
|
||||
int ret;
|
||||
#if __UNIX__
|
||||
@ -110,7 +111,7 @@ R_API void r_socket_printf(int fd, const char *fmt, ...)
|
||||
}
|
||||
|
||||
#if __UNIX__
|
||||
R_API int r_socket_unix_connect(char *file)
|
||||
R_API int r_socket_unix_connect(const char *file)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int sock;
|
||||
@ -191,14 +192,12 @@ R_API int r_socket_connect(char *host, int port)
|
||||
|
||||
if (connect(s, (const struct sockaddr*)&sa, sizeof(struct sockaddr)))
|
||||
return -1;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
R_API int r_socket_listen(int port)
|
||||
{
|
||||
int s;
|
||||
int ret;
|
||||
int ret, s;
|
||||
struct sockaddr_in sa;
|
||||
struct linger linger = { 0 };
|
||||
linger.l_onoff = 1;
|
||||
@ -223,7 +222,6 @@ R_API int r_socket_listen(int port)
|
||||
ret = listen(s, 1);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -258,7 +256,6 @@ R_API int r_socket_flush(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
R_API int r_socket_fgets(int fd, char *buf, int size)
|
||||
{
|
||||
int i = 0;
|
||||
@ -267,21 +264,23 @@ R_API int r_socket_fgets(int fd, char *buf, int size)
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
while(i<size-1) {
|
||||
while(i<size) {
|
||||
ret = r_socket_read(fd, (ut8 *)buf+i, 1);
|
||||
if (ret==0)
|
||||
return -1;
|
||||
break;
|
||||
if (ret<0) {
|
||||
r_socket_close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (buf[i]=='\r'||buf[i]=='\n')
|
||||
if (buf[i]=='\r'||buf[i]=='\n') {
|
||||
buf[i]='\0';
|
||||
break;
|
||||
i+=ret;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
buf[i]='\0';
|
||||
|
||||
return ret;
|
||||
return i;
|
||||
}
|
||||
|
||||
R_API char *r_socket_to_string(int fd)
|
||||
|
26
libr/socket/t/test.c
Normal file
26
libr/socket/t/test.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include <r_socket.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret;
|
||||
struct r_socket_proc_t *sp;
|
||||
char buf[256];
|
||||
char *const args[4] = { "/usr/bin/telnet", "localhost", "9999", 0 };
|
||||
|
||||
sp = r_socket_proc_open(args);
|
||||
// ret = r_socket_proc_read(sp, buf, 128);
|
||||
r_socket_proc_printf(sp, "GET / HTTP/1.1\r\n\r\n");
|
||||
printf("Waiting...\n");
|
||||
for(;;){
|
||||
if (!r_socket_proc_ready(sp, 0,0))
|
||||
break;
|
||||
ret = r_socket_proc_fgets(sp, buf, 128);
|
||||
printf("RET=%d\n", ret);
|
||||
if (ret<0) break;
|
||||
else if (ret>0)
|
||||
printf("%d=\"%s\"\n", ret, buf);
|
||||
else printf("--\n");
|
||||
}
|
||||
r_socket_proc_close(sp);
|
||||
return 0;
|
||||
}
|
23
libr/socket/t/testls.c
Normal file
23
libr/socket/t/testls.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <r_socket.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int ret;
|
||||
struct r_socket_proc_t *sp;
|
||||
char buf[256];
|
||||
char *const args[3] = { "/bin/ls", "-l", 0 };
|
||||
|
||||
sp = r_socket_proc_open(args);
|
||||
// ret = r_socket_proc_read(sp, buf, 128);
|
||||
|
||||
for(;;){
|
||||
if (!r_socket_proc_ready(sp, 0,0))
|
||||
break;
|
||||
ret = r_socket_proc_fgets(sp, buf, 128);
|
||||
if (ret>0)
|
||||
printf("%d=\"%s\"\n", ret, buf);
|
||||
else break;
|
||||
}
|
||||
r_socket_proc_close(sp);
|
||||
return 0;
|
||||
}
|
@ -5,10 +5,12 @@ PFX=$2
|
||||
LIST=$1.list
|
||||
|
||||
if [ "${PFX}" = "r_util" ]; then
|
||||
echo "=> No stripping any symbol in libr_util O:)"
|
||||
exit 0
|
||||
PFX="r_"
|
||||
fi
|
||||
|
||||
nm --defined-only -B ${FILE} 2>/dev/null | grep -v ${PFX}_ | awk '{print $3}' > ${LIST}
|
||||
nm --defined-only -B ${FILE} 2>/dev/null | grep -v ^${PFX}_ | awk '{print $3}' > ${LIST}
|
||||
#if [ -n "`cat /tmp/list`" ]; then
|
||||
echo "=> Stripping unnecessary symbols for ${FILE}..."
|
||||
objcopy --strip-symbols ${LIST} ${FILE} 2>/dev/null
|
||||
|
@ -3,11 +3,24 @@
|
||||
#include "r_types.h"
|
||||
#include "r_util.h"
|
||||
|
||||
#if 0
|
||||
/* TODO: the basic object lifecycle must be simplified */
|
||||
struct r_class_t {
|
||||
// new/free are implicit
|
||||
.init = &r_buf_init,
|
||||
.fini = &r_buf_fini,
|
||||
} r_buf_class;
|
||||
|
||||
#define r_buf_init(x) r_buf_class->init
|
||||
#endif
|
||||
|
||||
R_API struct r_buf_t *r_buf_init(struct r_buf_t *b)
|
||||
{
|
||||
b->length = 0;
|
||||
b->base = 0LL;
|
||||
b->buf = NULL;
|
||||
if (b) {
|
||||
b->length = 0;
|
||||
b->base = 0LL;
|
||||
b->buf = NULL;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -17,16 +30,24 @@ R_API struct r_buf_t *r_buf_new()
|
||||
return r_buf_init(b);
|
||||
}
|
||||
|
||||
R_API void r_buf_set_bytes(struct r_buf_t *b, ut8 *buf, int length)
|
||||
R_API int r_buf_set_bits(struct r_buf_t *b, int bitoff, int bitsize, ut64 value)
|
||||
{
|
||||
// TODO: implement r_buf_set_bits
|
||||
// TODO: get the implementation from reg/value.c ?
|
||||
}
|
||||
|
||||
R_API int r_buf_set_bytes(struct r_buf_t *b, ut8 *buf, int length)
|
||||
{
|
||||
free(b->buf);
|
||||
b->buf = malloc(length);
|
||||
if (b->buf == NULL)
|
||||
return R_FALSE;
|
||||
memcpy(b->buf, buf, length);
|
||||
b->length = length;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
static int r_buf_memcpy(struct r_buf_t *b, ut64 addr, ut8 *dst, ut8 *src, int len)
|
||||
{
|
||||
static int r_buf_memcpy(struct r_buf_t *b, ut64 addr, ut8 *dst, ut8 *src, int len) {
|
||||
int end;
|
||||
addr -= b->base;
|
||||
if (addr > b->length)
|
||||
@ -43,13 +64,18 @@ R_API int r_buf_read_at(struct r_buf_t *b, ut64 addr, ut8 *buf, int len)
|
||||
return r_buf_memcpy(b, addr, buf, b->buf, len);
|
||||
}
|
||||
|
||||
R_API int r_buf_write_at(struct r_buf_t *b, ut64 addr, ut8 *buf, int len)
|
||||
R_API int r_buf_write_at(struct r_buf_t *b, ut64 addr, const ut8 *buf, int len)
|
||||
{
|
||||
return r_buf_memcpy(b, addr, b->buf, buf, len);
|
||||
}
|
||||
|
||||
R_API void r_buf_free(struct r_buf_t *b)
|
||||
R_API void r_buf_deinit(struct r_buf_t *b)
|
||||
{
|
||||
free(b->buf);
|
||||
}
|
||||
|
||||
R_API void r_buf_free(struct r_buf_t *b)
|
||||
{
|
||||
r_buf_deinit(b);
|
||||
free(b);
|
||||
}
|
||||
|
@ -2,24 +2,24 @@
|
||||
|
||||
#include <r_util.h>
|
||||
|
||||
void r_cache_init(struct r_cache_t *c)
|
||||
R_API void r_cache_init(struct r_cache_t *c)
|
||||
{
|
||||
INIT_LIST_HEAD(&c->items);
|
||||
}
|
||||
|
||||
struct r_cache_t *r_cache_new()
|
||||
R_API struct r_cache_t *r_cache_new()
|
||||
{
|
||||
struct r_cache_t *a = MALLOC_STRUCT(struct r_cache_t);
|
||||
r_cache_init(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void r_cache_free(struct r_cache_t *a)
|
||||
R_API void r_cache_free(struct r_cache_t *a)
|
||||
{
|
||||
free(a);
|
||||
}
|
||||
|
||||
char *r_cache_get(struct r_cache_t *c, ut64 addr)
|
||||
R_API char *r_cache_get(struct r_cache_t *c, ut64 addr)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each_prev(pos, &c->items) {
|
||||
@ -30,7 +30,7 @@ char *r_cache_get(struct r_cache_t *c, ut64 addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int r_cache_set(struct r_cache_t *c, ut64 addr, char *str)
|
||||
R_API int r_cache_set(struct r_cache_t *c, ut64 addr, char *str)
|
||||
{
|
||||
struct r_cache_item_t *a = MALLOC_STRUCT(struct r_cache_item_t);
|
||||
a->addr = addr;
|
||||
@ -39,7 +39,7 @@ int r_cache_set(struct r_cache_t *c, ut64 addr, char *str)
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
int r_cache_validate(struct r_cache_t *c, ut64 from, ut64 to)
|
||||
R_API int r_cache_validate(struct r_cache_t *c, ut64 from, ut64 to)
|
||||
{
|
||||
int ret = R_FALSE;
|
||||
struct list_head *pos, *n;
|
||||
@ -55,7 +55,7 @@ int r_cache_validate(struct r_cache_t *c, ut64 from, ut64 to)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int r_cache_invalidate(struct r_cache_t *c, ut64 from, ut64 to)
|
||||
R_API int r_cache_invalidate(struct r_cache_t *c, ut64 from, ut64 to)
|
||||
{
|
||||
int ret = R_FALSE;
|
||||
struct list_head *pos, *n;
|
||||
|
@ -3,7 +3,16 @@
|
||||
#include <r_util.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
R_API void r_mem_copyloop (ut8 *dest, const ut8 *orig, int dsize, int osize)
|
||||
// TODO: find better name
|
||||
R_API int r_mem_count(ut8 **addr)
|
||||
{
|
||||
int i = 0;
|
||||
while(*addr++)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
R_API void r_mem_copyloop(ut8 *dest, const ut8 *orig, int dsize, int osize)
|
||||
{
|
||||
int i=0,j;
|
||||
while(i<dsize)
|
||||
|
@ -6,6 +6,10 @@
|
||||
#define ALLOC_POOL_SIZE 1024
|
||||
#define ALLOC_POOL_COUNT 128
|
||||
|
||||
// TODO: add api to serialize/deserialize memory pools from/to disk
|
||||
// This can be useful when the application is swapping (userland swapping?)
|
||||
// Do user-swapping takes sense?
|
||||
|
||||
R_API struct r_mem_pool_t* r_mem_pool_deinit(struct r_mem_pool_t *pool)
|
||||
{
|
||||
int i;
|
||||
@ -51,6 +55,8 @@ R_API void* r_mem_pool_alloc(struct r_mem_pool_t *pool)
|
||||
return NULL;
|
||||
}
|
||||
pool->nodes[pool->npool] = malloc (pool->nodesize*pool->poolsize);
|
||||
if (pool->nodes[pool->npool] == NULL)
|
||||
return NULL;
|
||||
pool->ncount = 0;
|
||||
}
|
||||
// TODO: fix warning
|
||||
|
@ -197,11 +197,11 @@ R_API char *r_str_trim(char *str)
|
||||
}
|
||||
|
||||
/* memccmp("foo.bar", "foo.cow, '.') == 0 */
|
||||
R_API int r_str_ccmp(const char *dst, const char *orig, int ch)
|
||||
R_API int r_str_ccmp(const char *dst, const char *src, int ch)
|
||||
{
|
||||
int i;
|
||||
for(i=0;orig[i] && orig[i] != ch; i++)
|
||||
if (dst[i] != orig[i])
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
if (dst[i] != src[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@ -217,11 +217,11 @@ R_API int r_str_cmp(const char *a, const char *b, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_str_ccpy(char *dst, char *orig, int ch)
|
||||
R_API int r_str_ccpy(char *dst, char *src, int ch)
|
||||
{
|
||||
int i;
|
||||
for(i=0;orig[i] && orig[i] != ch; i++)
|
||||
dst[i] = orig[i];
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
dst[i] = src[i];
|
||||
dst[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include <r_util.h>
|
||||
|
||||
char *buf[] = { "eax", "ebx", "ecx", NULL };
|
||||
|
||||
int main()
|
||||
{
|
||||
struct r_mem_pool_t *pool = r_mem_pool_new(128, 0, 0);
|
||||
void *foo = r_mem_pool_alloc(pool);
|
||||
foo = r_mem_pool_alloc(pool);
|
||||
|
||||
printf("%d\n", r_mem_count(buf));
|
||||
|
||||
r_mem_pool_free(pool);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2009 nibble<.ds@gmail.com> */
|
||||
/* radare - LGPL - Copyright 2009 pancake<@nopcode.org> */
|
||||
|
||||
[CCode (cheader_filename="r_reg.h", cprefix="r_reg_", lower_case_cprefix="r_reg_")]
|
||||
namespace Radare {
|
||||
@ -46,7 +46,7 @@ namespace Radare {
|
||||
public Register();
|
||||
public bool set_profile(string file);
|
||||
public bool set_profile_string(string profile);
|
||||
public Register.Item get(string name);
|
||||
public Register.Item get(string name, int type = -1);
|
||||
public Radare.List<Register.Item*> get_list(Register.Type type);
|
||||
|
||||
public uint64 get_value(Register.Item item);
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* This vapi has been manually generated by me */
|
||||
|
||||
/* TODO: Add simpletype instead of int so, we can use it as an object */
|
||||
|
||||
[CCode (cheader_filename="r_socket.h", cprefix="r_socket", lower_case_cprefix="r_socket_")]
|
||||
namespace Radare.Socket {
|
||||
public bool ready(int fd, int secs, int usecs);
|
||||
@ -14,5 +16,11 @@ namespace Radare.Socket {
|
||||
public int fgets(int fd, string *buf, int len);
|
||||
public int printf(int fd, string *str, ...);
|
||||
public int accept(int fd);
|
||||
public string to_string(int fd);
|
||||
public void block(int fd, bool blocking);
|
||||
public bool flush(int fd);
|
||||
public owned string to_string(int fd);
|
||||
|
||||
/* UNIX ONLY */
|
||||
public int unix_connect(string file);
|
||||
public int unix_listen(string file);
|
||||
}
|
||||
|
@ -25,10 +25,19 @@ namespace Radare {
|
||||
public int hash(string str);
|
||||
}
|
||||
|
||||
[CCode (cprefix="r_log")]
|
||||
public static class Log {
|
||||
public bool msg(string str);
|
||||
public bool err(string str);
|
||||
}
|
||||
|
||||
[CCode (cprefix="r_buf")]
|
||||
public class Buffer {
|
||||
public Buffer();
|
||||
public int read(uint64 addr, uint8 *buf, int len);
|
||||
public int read_at(uint64 addr, uint8 *buf, int len);
|
||||
public int write_at(uint64 addr, uint8 *buf, int len);
|
||||
public bool set_bytes(uint8 *buf, int len);
|
||||
public bool memcpy(uint64 addr, uint8 *dst, uint8 *src, int len);
|
||||
/* ... */
|
||||
}
|
||||
|
||||
@ -89,4 +98,6 @@ namespace Radare {
|
||||
[CCode (cname="rarray_iterator")] //, generic_type_pos=2)]
|
||||
public Rarray<G> iterator();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user