

				----------------------------
				Libelfsh 0.43b API reference
				----------------------------


XXX: Need to be updated to 0.5 . For a complete list of the libelfsh 0.5 serie
API calls, read ../libelfsh/include/libelfsh.h .


-------


This is the first documentation for libelfsh-0.43b . You should definitely look at
the testsuite to understand how to do basic things .

Structures has been created :

- Elfsh32_Obj is the main object, describing the object itself, look at libelfsh.h for details .
- Elfsh32_Sect describes a section in the binary, contains a field pointing to its SHT entry .
- Elfsh32_Func describe a function . For the moment, Elf32_Func are created using .symtab .
- All structures beginning with Elfsh32_ are not OS native, they are elfsh specifics .



An ELFsh object look like that :


/* ELF object structure */
typedef struct	s_obj
{
  
  int		fd;		/* File descriptor for the original file */
  char		*name;		/* Object path */
  int		type;		/* ELFSH_OBJECT_CORE, ELFSH_OBJECT_SHARED, ELFSH_OBJECT_RELOC or ELFSH_OBJECT_EXEC */
  
  /* Elf headers */
  Elf32_Ehdr	*hdr;
  Elf32_Shdr	*sht;
  Elf32_Phdr	*pht;

  /* Section linked list */
  Elfsh32_Sect	*sections;

  /* Unlinked sections */
  Elfsh32_Sect	*sections_bean;

  /* ********************************************************************************** */
  /* The following variables point to their respective entry in the section linked list */
  /* ********************************************************************************** */

  /* Symbol table related fields */
  Elfsh32_Sect	*symtab;

  /* Dynamic symbol table related fields */
  Elfsh32_Sect	*dynsym;

  /* Stab section fields (debugging symbols) */
  Elfsh32_Sect	*stab;

  /* Symbol Hash (.hash) table fields */
  Elfsh32_Sect	*hash;

  /* Dynamic structure fields (PT_DYNAMIC) */
  Elfsh32_Sect	*dynamic;

  /* Constructors */
  Elfsh32_Sect	*ctors;

  /* Destructors */
  Elfsh32_Sect	*dtors;

  /* Global Offset Table fields */
  Elfsh32_Sect	*got;
  
  /* Procedure Linkage Table (.plt) object */
  Elfsh32_Sect	*plt;

  /* Interpretor section (PT_INTERP) */
  Elfsh32_Sect	*interp;

  /* Symbol string table (.strtab) */
  Elfsh32_Sect	*strtab;

  /* Stab string table (.stabstr) */
  Elfsh32_Sect	*stab_strtab;
  
  /* Dynamic symbol string table (.dynstr) */
  Elfsh32_Sect	*dyn_strtab;

  /* Section string table (.shstrtab) */
  Elfsh32_Sect	*sh_strtab;

  /* Various internal fields for error handling */
  char		buff[ELFSH_RULEZ_THE_WORLD];
  const char	*error;

  /* Has the object already been function scanned ? */
  char		scanned;		

  /* Do we include the sht in the output file ? Default is YES (1) */
  char		remove_sht_on_exit;

  /* The list is double linked */
  void		*next;
  void		*prev;

}		Elfsh32_Obj;



The Elfsh32_Sect object looks like this : 


/* Section data type */
typedef struct		s_sect
{

  /* Filled at creation */
  Elf32_Phdr		*phdr;		/* the first parent segment					*/
  Elf32_Shdr		*shdr;		/* section header for this section				*/
  struct s_sect		*next;		/* next section in the list					*/
  struct s_sect		*prev;		/* prev section in the list					*/
  struct s_obj		*parent;	/* parent ELF object file					*/	
  int			index;		/* Section index in sht						*/
  char			flags;		/* Analysed/Raw, Orphelin/Child					*/
  char			*name;		/* Cached name							*/

  /* Filled at loading */
  void			*data;		/* section's data cache						*/
  int			nbr;		/* Number of units (section type dependant)			*/

  /* Filled at analysing */
  void			*altdata;	/* symtab stores a sorted table here, +x section stores the fht */
  int			altnbr;		/* Number of units for altdata					*/

}			Elfsh32_Sect;





Now lets look at the API itself :



##############
ERROR HANDLING
##############

On errors, the incriminated API call will return (-1) or NULL, depending on the return type .

Print the last error message on STDERR :

void		elfsh_error();




################################
MAIN OBJECTS ACCESSIBILITY CALLS  
################################


These 2 first functions are used to create the Elfsh32_Obj entity in memory, if you plan
to modify the file, then you have to use elfsh_map_obj() . If you just want to read things, 
then use elfsh_load_obj() . The main difference between them is that elfsh_load_obj() fills
data field on demand, whereas elfsh_map_obj() loads everything .

Elfsh32_Obj	*elfsh_load_obj(char *name);
Elfsh32_Obj	*elfsh_map_obj(char *name);


Unload an object without saving :

void		elfsh_unload_obj(Elfsh32_Obj *file);

Save changes and unload an object :

int		elfsh_save_obj(Elfsh32_Obj *file, char *name);


Retreive the ELF header, the returned type is (Elf32_Ehdr *) :

void		*elfsh_get_hdr(Elfsh32_Obj *file);


Get/Set various ELF header fields :

u_int		elfsh_get_objtype(Elf32_Ehdr *e);
u_int		elfsh_get_arch(Elf32_Ehdr *e);
void		elfsh_set_entry_point(Elfsh32_Obj *file, int addr);




#####################
SYMBOLS RELATED CALLS
#####################



Some calls are identical for .dynsym symbols and .symtab symbols . Here is the list :

Elf32_Sym	*elfsh_create_symbol(int value, int size, int type, int binding, int visibility);
Elf32_Sym	*elfsh_copy_symtab(void *addr, int size);
Elf32_Sym	*elfsh_merge_symtabs(Elf32_Sym *one, Elf32_Sym *two, int size_one, int size_two);
void		*elfsh_get_symbol_offset(Elf32_Sym *s);
u_int		elfsh_get_symbol_bind(Elf32_Sym *s);
u_int		elfsh_get_symbol_type(Elf32_Sym *s);
int		elfsh_insert_symbol(Elfsh32_Sect *sect, Elf32_Sym *sym, char *name);
int		elfsh_get_symbol_foffset(Elfsh32_Obj *file, Elf32_Sym *sym);
int		elfsh_get_symbol_size(Elf32_Sym *s);

There is 2 sorts possible : 
  . ELFSH_SORT_BY_ADDR sort symbols by address .
  . ELFSH_SORT_BY_SIZE sort symbols by size .

int		elfsh_sort_symtab(Elf32_Sym *symtab, int size, int type);




 * These are especialy for 'static' symbols (.symtab entries) :

Useful function : It returns the nearest symbol name matching with sym_value and fill the
difference in *offset :

Elf32_Sym	*elfsh_get_symbol_by_name(Elfsh32_Obj *file, char *name);
char		*elfsh_get_symbol_name(Elfsh32_Obj *file, Elf32_Sym *s);
char		*elfsh_reverse_symbol(Elfsh32_Obj *file, u_int sym_value, int *offset);
void		*elfsh_get_symtab(Elfsh32_Obj *file, int *num);



 * These are especially for dynamic symbols (.dynsym entries) :


Elf32_Sym	*elfsh_get_dynsymbol_by_name(Elfsh32_Obj *file, char *name);
void		*elfsh_get_dynsymtab(Elfsh32_Obj *file, int *num);
char		*elfsh_reverse_dynsymbol(Elfsh32_Obj *file, u_int sym_value, int *offset);
char		*elfsh_get_dynsymbol_name(Elfsh32_Obj *file, Elf32_Sym *s);
Elf32_Sym	*elfsh_get_symbol_from_reloc(Elfsh32_Obj *file, Elf32_Rel *s);




################################
SECTION HEADER TABLE (SHT) CALLS
################################


Return the section header giving a STT_SECTION symbols found in .symtab :

Elf32_Shdr      *elfsh_get_shtentry_from_sym(Elfsh32_Obj *file, Elf32_Sym *sym);


Return the section header table (Elf32_Shdr *) and fill the number of entries in *num :

void		*elfsh_get_sht(Elfsh32_Obj *file, int *num);


Theses calls returns info about a given section header :

int		elfsh_section_is_executable(Elf32_Shdr *s);
int		elfsh_section_is_writable(Elf32_Shdr *s);
int		elfsh_section_is_allocatable(Elf32_Shdr *s);
int		elfsh_section_is_mergeable(Elf32_Shdr *s);
int		elfsh_section_is_strtab(Elf32_Shdr *s);
int		elfsh_section_has_link(Elf32_Shdr *s);
int		elfsh_section_has_order(Elf32_Shdr *s);
int		elfsh_get_section_size(Elf32_Shdr *s);
int		elfsh_get_section_align(Elf32_Shdr *s);
int		elfsh_get_section_vaddr(Elf32_Shdr *s);
int		elfsh_get_section_foffset(Elf32_Shdr *s);
u_int		elfsh_get_section_type(Elf32_Shdr *s);
u_int		elfsh_get_section_info(Elf32_Shdr *s);
u_int		elfsh_get_section_entsize(Elf32_Shdr *s);
u_int		elfsh_get_section_link(Elf32_Shdr *s);


Returns the section names provided .shstrtab is loaded (true by default ;) :

char		*elfsh_get_section_name(Elfsh32_Obj *file, Elf32_Shdr *s);


Changes fields in a SHT entry :

void		elfsh_set_sht_offset(Elfsh32_Obj *file, int num);
void		elfsh_set_sht_nbr(Elfsh32_Obj *file, int num);
void		elfsh_set_section_info(Elf32_Shdr *s, Elf32_Word info);
void		elfsh_set_section_entsize(Elf32_Shdr *s, Elf32_Word entsize);
void		elfsh_set_section_link(Elf32_Shdr *s, Elf32_Word link);
void		elfsh_set_section_foffset(Elf32_Shdr *s, Elf32_Off offset);
void		elfsh_set_section_addr(Elf32_Shdr *s, Elf32_Addr addr);


These 2 calls exists because the section injection and the section header table entry injection
are not the same . You need to insert a SHT entry before inserting the Section itself . Look at
the testsuite to know the exact syntax for Section injection .

Elf32_Shdr	elfsh_create_section_header(Elf32_Word name, Elf32_Word type, Elf32_Word flags,
					    Elf32_Addr addr, Elf32_Off offset, Elf32_Word size,
					    Elf32_Word link, Elf32_Word info, Elf32_Word align,
					    Elf32_Word entsize);

You shouldnt use this one except if you know exactly what you are doing . If you want to insert a section
you should look at elfsh_insert_(un)mapped_section() in the next paragraph . This call insert a Section 
header exactly where you want it to be inserted :

int		elfsh_insert_section_header(Elfsh32_Obj *file, Elf32_Shdr hdr, u_int range, char *name);


Rebuild a minimal Section header table if not present anymore . Very useful to disassemble
using bfd based tools (BFD doesnt rekognize ELF binary without SHT ;( :

int		elfsh_rebuild_sht(Elfsh32_Obj *file);


Used to indicate elfsh not to insert SHT when relinking using elfsh_save_obj() :

void		elfsh_remove_sht(Elfsh32_Obj *file);



######################
SECTION RELATED CALLS
######################


Search for a 'range'th section whoose type is 'type', filling the index, strindex and num field if ptr are non null :

 - 'index' is the index for this section .
 - 'strindex' is the section index for the linked string section (if one) .
 - 'num' is the number of element for this section .

Elfsh32_Sect	*elfsh_get_section_by_type(Elfsh32_Obj *, u_int type, int *index, int *strindex, int *num, int range);


Search a section using its index in SHT :

Elfsh32_Sect	*elfsh_get_section_by_index(Elfsh32_Obj *, int index, int *strindex, int *num);


Search a section giving its name :


Elfsh32_Sect	*elfsh_get_section_by_name(Elfsh32_Obj *, char *name, int *idx, int *strindex, int *num);


Return the parent Section giving a virtual address . The difference is filled in *offset :

Elfsh32_Sect	*elfsh_get_parent_section(Elfsh32_Obj *file, u_int value, int *offset);


The same function, this time using a file offset (useful for non mapped sections) :

Elfsh32_Sect	*elfsh_get_parent_section_by_foffset(Elfsh32_Obj *file, u_int value, int *offset);


Create a section in order to inject it (or not) . Look at the testsuite for exact syntax :

Elfsh32_Sect	*elfsh_create_section(char *name);


Load (force read related data in the file) a section in the Elfsh32_Obj structure :

void		*elfsh_get_anonymous_section(Elfsh32_Obj *file, Elfsh32_Sect *sect);


Insert a memory mapped section in the binary, and inject byts pointed by 'data' in it . Inject the number 
of byte indicated in hdr.sh_size . The difference between the 2 is that the last one have to put the .bss
section physically in the file before (if not already done) .

int		elfsh_insert_unmapped_section(Elfsh32_Obj *file, Elfsh32_Sect *sect, Elf32_Shdr hdr, void *data)
int		elfsh_insert_mapped_section(Elfsh32_Obj *file, Elfsh32_Sect *sect, Elf32_Shdr hdr, void *data)

Append random data to a section :

int		elfsh_append_data_to_section(Elfsh32_Sect *sect, void *input, int len);



###################################
PROGRAM HEADER RELATED (PHT) CALLS
###################################


Return a (Elf32_Phdr *) and fill *num with the PHT entries number :

void		*elfsh_get_pht(Elfsh32_Obj *file, int *num);
Elf32_Phdr	*elfsh_get_segment_by_type(Elfsh32_Obj *file, int type, int range);
Elf32_Phdr	*elfsh_get_parent_segment(Elfsh32_Obj *file, Elfsh32_Sect *new);
int		elfsh_load_pht(Elfsh32_Obj *file);
int		elfsh_segment_is_writable(Elf32_Phdr *p);
int		elfsh_segment_is_readable(Elf32_Phdr *p);
int		elfsh_segment_is_executable(Elf32_Phdr *p);
int		elfsh_segment_is_parent(Elfsh32_Sect *new, Elf32_Phdr *p);
u_int		elfsh_get_segment_type(Elf32_Phdr *p);

This change values in the ELF header :

void		elfsh_set_pht_offset(Elfsh32_Obj *file, int num);
void		elfsh_set_pht_nbr(Elfsh32_Obj *file, int num);




##############################
.DYNAMIC SECTION RELATED CALLS
##############################



Elf32_Dyn	*elfsh_get_dynamic(Elfsh32_Obj *file, int *num);
Elf32_Dyn	*elfsh_get_dynamic_entry_by_type(Elfsh32_Obj *file, char type);
char		*elfsh_get_dynentry_info(Elfsh32_Obj *file, Elf32_Dyn *d);
u_int		elfsh_get_dynentry_type(Elf32_Dyn *d);





#################################
GOT / DTORS / CTORS RELATED CALLS
#################################

In all cases, the 'num' parameter is filled by the called function and indicate the number
of entries for this section (in this case, the number of 4 bytes dwords in the section, 
in other word, section->sh_size / 4 .

Modify an entry in the .got section, used to hijack library calls :

void		*elfsh_get_got(Elfsh32_Obj *file, int *num);
int		elfsh_set_got_entry_by_name(Elfsh32_Obj *file, char *name, int new_addr);
int		elfsh_set_got_entry_by_index(Elfsh32_Obj *file, int index, int new_addr);


Modify an entry in the .dtors section, used to hijack destructors functions :

void		*elfsh_get_dtors(Elfsh32_Obj *file, int *num);
int		elfsh_set_dtors_entry_by_index(Elfsh32_Obj *file, int index, int new_addr);
int		elfsh_set_dtors_entry_by_name(Elfsh32_Obj *file, char *name, int new_addr);

Modify an entry in the .ctors section, used to hijack constructors functions :

void		*elfsh_get_ctors(Elfsh32_Obj *file, int *num);
int		elfsh_set_ctors_entry_by_name(Elfsh32_Obj *file, char *name, int new_addr);
int		elfsh_set_ctors_entry_by_index(Elfsh32_Obj *file, int index, int new_addr);




###################
STABS RELATED CALLS
###################

'Num' is filled by the called function with the number of stab entries in the
returned section .

Read-only interface for STABS :

void		*elfsh_get_stab(Elfsh32_Obj *file, int *num);
void		*elfsh_get_stab_offset(Elfsh32_Stab_ent *s);	       
char		*elfsh_get_stab_name(Elfsh32_Obj *file, Elfsh32_Stab_ent *s);
u_int		elfsh_get_stab_type(Elfsh32_Stab_ent *s);




###################
.HASH RELATED CALLS
###################


These implement a wrapper for .hash as described in the ELF reference .

int		elfsh_get_symbol_hash(char *sym_name);
int		elfsh_get_dynsymbol_by_hash(Elfsh32_Obj *file, char *sym_name);




########################
RELOCATION RELATED CALLS
########################

Elfsh32_Sect	*elfsh_get_reloc(Elfsh32_Obj *file, u_int range, char *name, u_int *num);
void		*elfsh_get_reloffset(Elfsh32_Obj *file, Elf32_Rel *r);
void		elfsh_free_reloc_list(Elfsh32_Obj *file);
u_int		elfsh_get_reloc_type(Elf32_Rel *r);



#####################
.INTERP RELATED CALLS
#####################

char		*elfsh_get_interp(Elfsh32_Obj *file);



####################
.NOTES RELATED CALLS
####################


Elfsh32_Sect	*elfsh_get_notes(Elfsh32_Obj *file, u_int range, char *name);
void		elfsh_free_notes_list(Elfsh32_Obj *file);



#######################
FUNCTIONS RELATED CALLS
#######################

You may not use for writing purpose since the interface for it is not clearly
defined for the moment . The implementation of this is pretty weak since it
relies on .symtab instead of parsing the code, but this is in the TODO list .

Elfsh32_Func	*elfsh_get_function_by_addr(Elfsh32_Obj *file, int addr);
Elfsh32_Func    *elfsh_get_function_by_name(Elfsh32_Obj *file, char *name);
int		elfsh_get_function_len(Elfsh32_Func *func);
int		elfsh_get_function_addr(Elfsh32_Func *func);



###########################################
PROCEDURE LINKAGE TABLE (PLT) RELATED CALLS
###########################################


Elfsh32_Sect	*elfsh_get_plt(Elfsh32_Obj *file, int *num);

Useful to fingerprint STT_FUNCTION typed symbols and guess if its pointing in .plt :

int		elfsh_is_pltentry(Elfsh32_Obj *file, Elf32_Sym *sym);
int		elfsh_is_plt(Elfsh32_Obj *file, Elf32_Shdr *s);




###################################
RAW READ/WRITE ACCESS RELATED CALLS
###################################


Use this for multiple purpose :

int		elfsh_raw_write(Elfsh32_Obj *file, u_int dst, void *src, int len);
int		elfsh_raw_read(Elfsh32_Obj *file, u_int dst, void *src, int len);
int		elfsh_get_foffset_from_vaddr(Elfsh32_Obj *file, u_int vaddr);



######################### 
.(SH)STRTAB RELATED CALLS
#########################



Useful to add a just-inserted symbol name in the binary :

int		elfsh_insert_in_strtab(Elfsh32_Obj *file, char *name);

Useful to add a just_inserted section name in the binary :

int		elfsh_insert_in_shstrtab(Elfsh32_Obj *file, char *name);



















