Reading ELF String Table on Linux from C - elf

I want to write a program which reads the string table of a binary. Binary is in ELF running on REDHAT linux 32.
I did the following -
Read the Elf Header
Read all the sections
Below is the output of my progam.
Entry Address of Binary - 0x8048340
Start of Program Header - 52
Start of section header - 3272
Size of header - 52
Number of section headers - 36
Size of each section headers - 40
Number of section headers - 36
Section header Offset - 3272
string tbl index for section[0] is 0
string tbl index for section[1] is 27
string tbl index for section[7] is 35
string tbl index for section[1879048182] is 49
string tbl index for section[11] is 59
string tbl index for section[3] is 67
string tbl index for section[1879048191] is 75
string tbl index for section[1879048190] is 88
string tbl index for section[9] is 103
string tbl index for section[9] is 112
string tbl index for section[1] is 121
string tbl index for section[1] is 116
string tbl index for section[1] is 127
string tbl index for section[1] is 133
string tbl index for section[1] is 139
string tbl index for section[1] is 147
string tbl index for section[1] is 157
string tbl index for section[1] is 164
string tbl index for section[1] is 171
string tbl index for section[6] is 176
string tbl index for section[1] is 185
string tbl index for section[1] is 190
string tbl index for section[1] is 199
string tbl index for section[8] is 205
string tbl index for section[1] is 210
string tbl index for section[1] is 219
string tbl index for section[1] is 234
string tbl index for section[1] is 250
string tbl index for section[1] is 262
string tbl index for section[1] is 276
string tbl index for section[1] is 288
string tbl index for section[1] is 301
string tbl index for section[1] is 312
string tbl index for section[3] is 17
string tbl index for section[2] is 1
string tbl index for section[3] is 9
I understand that sh_name in Elf32_Shdr is basically an index to String table which actually contains a NULL terminated String. I want to display this null terminated String. I have a question here -
In the above output, we can see that there are multiple entries for Section Headers which have sh_type = 3 (SHT_STRTAB). So i do not understand how do i map the index(sh_name in Elf32_Shdr) to which section?
Upon printing the Elf32_Shdr for sections having sh_type = 3 i get the following output -
Section header Offset - 3272
sh_name - 67
sh_type - 3
sh_flags - 2
sh_addr - 80481e8
sh_offset - 488
sh_size - 94
sh_link - 0
sh_info - 0
sh_addralign - 1
sh_entsize - 0
--------------------------------------------------------------
sh_name - 17
sh_type - 3
sh_flags - 0
sh_addr - 0
sh_offset - 2948
sh_size - 323
sh_link - 0
sh_info - 0
sh_addralign - 1
sh_entsize - 0
--------------------------------------------------------------
sh_name - 9
sh_type - 3
sh_flags - 0
sh_addr - 0
sh_offset - 6008
sh_size - 664
sh_link - 0
sh_info - 0
sh_addralign - 1
sh_entsize - 0
--------------------------------------------------------------

I was able to find out the answer myself :). Although it took a lot of time to code. Here is how it is done if someone wants to refer it for future -
Each Binary generally contains three String tables -
1. .dynstr
2. .shstrtab
3. .strtab
IN the above question we are concerned with .shstrtab which when expanded stands for - Section Header STRing TABle. Upon reading the ELF header we find the following field in ELF header - e_shstrndx. This is the index where we can find .shstrtab. Following formula can be used to calculate how it will be done -
offset = ((elfHdr.e_shstrndx)*elfHdr.e_shentsize)+elfHdr.e_shoff
Meaning of each parameter -
elfHdr.e_shstrndx = index where we can find .shstrtab
elfHdr.e_shentsize = Size of each Section Header
elfHdr.e_shoff = Offset at which section header starts.

In brief, the e_shstrndx field of ELF Executable Header contains the index of the ELF string table holding section names.
The "libelf by Example" tutorial has a lengthier explanation, along with example code showing how to retrieve section names using the functions in the ELF(3) API.

Related

PDF How to get Font object with id not in cross reference table

Like in this discussion,
Tj command with angle brackets
I'm faced with TJ operator where content is between angle brackets:
<00030037005200570044004F000300550048004600520051005100580056>Tj
the parent page gives the list of font object id's like this
Font /C2_0 39 0 R/T1_0 41 0 R/T1_1 43 0 R/T1_2 44 0 R
and for the object where the angle brackets string is, a Tf operator specifies that the font reference is C2_0
So from the font list, I know the C2 font object is 39
Ok, but now, what is the fastest way to access this 39 object that is embedded in a stream object having 16 as id. In this #16 object, there is the list of embedded objects
32 0 33 106 34 131 35 141 36 193 37 436 38 16720 39 16728 ....
So my quetion is how to get the 16 value, when I only know that the font object id 39 is not in the cross reference table? Do I have to parse all stream objects and read their stream object list to detect which one has the object 39?
Thanks for your attention.

Get length from item set

I have a set of Data in this format
# Input Data for items in the format (i,l,w,h)
i for item, l for length , w for width, h for height
set itemData :=
271440 290 214 361
1504858 394 194 114
4003733 400 200 287
4012512 396 277 250
4013886 273 221 166;
I am trying to get the lengths of each item, using the following code
set IL = setof {i in items, (i,l,w,h) in itemData} (i,l); #length of item i
This method only does not allow me to access the individual item length.
What i am trying to do is to have
display IL[271440] = 290;
how can i go about doing this?
Careful with terminology. In AMPL terms, that table isn't a "set". You have a table of parameters. Your sets are the row and column indices for that table: {"l","w","h"} for the columns, and item ID numbers for the rows.
In AMPL it would be handled something like this:
(.mod part)
set items;
set attributes := {"l","w","h"};
param itemData{items, attributes};
(.dat part)
set items :=
271440
1504858
4003733
4012512
4013886
;
param itemData: l w h :=
271440 290 214 361
1504858 394 194 114
4003733 400 200 287
4012512 396 277 250
4013886 273 221 166
;
You can then do:
ampl: display itemData[271440,"l"];
itemData[271440,'l'] = 290
I think it's possible to define set "items" at the same time as itemData and avoid the need to duplicate the ID numbers. Section 9.2 of the AMPL Book shows how to do this for a parameter that has a single index set, but I'm not sure of the syntax for doing this when you have two index sets as above. (If anybody does know, please add it!)

Multiply by a cell formula

I am calculating the next excel table in VBA and leave the results as values because of a volume of data. But then I have to multiply these range by 1 or 0 depending on a column.
The problem is that I don't want to multiply by 0 becouse I gonna lose my data and have to recalculate it (I don't want it).
So, after my macro I get a next table, for example:
var.1 var.2 var.3
0 0 0
167 92 549
159 87 621
143 95 594
124 61 463
0 0 0
5 12 75
in a Range("A2:C9").
In a Range("A1:C1") i gonna have a 1 or 0 values that will be changing so i need my Range("A2:C9") to be like:
var.1 var.2 var.3
=0*A$1 =0*B$1 =0*C$1
=167*A$1 =92*B$1 =549*C$1
...
Is it possible to do with a macro? Thank's
And I would like to get
Okay so what I would do here is first copy the original data to another sheet or set of columns so that it is always preserved. Then use this formula:
=IF($A$1 = 0, 0,E3)
Instead of writing the cell E3 reference the data that you copied.

Split a string to its subwords

Every letter has a value
a b c d e f g h i j k l m n o p q r s t u v w x y z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
TableA
String Length Value Subwords
exampledomain 13 132 #example-domain#example-do-main#
creditcard 10 85 #credit-card#credit-car-d#
TableB
Words Length Value
example 7 76
do 2 19
main 4 37
domain 6 56
credit 6 59
card 4 26
car 3 22
d 1 4
Explanation
TableA has string based over milion rows, and it will be new added 100k rows/daily to tableA.
And also "string" column has no whitespaces
TableB has words based over milion rows,there is every letter and words in 1-2 languages
What i want to do
i want to split strings in TableA to its subwords, as you see in example; "creditcard" i search in TableB all words and try to find which words when comes together matches the string
What i did,and couldnt solve my question
i took the string and JOIN the TableB with INNER JOINS i made 2-3 times INNER JOINS because there can be 3word 4word strings too, and that WORKED!! but it takes too much time even doing it for 100-200 strings. Guess i want to do it for 100k/everyday???
Now what i try to do
i gave values to everyletter as you see above,
Took the strings one by one and from their including letters i count the value of strings..
And the same for the words too in TableB..
Now i have every string in TableA and everyword in TableB with their VALUES..
_
1- i will take the string,length and value of it (Exmple; creditcard - 10 - 85)
2- and make a search in TableB to find the possible words when they come together, with their SUM(length), and SUM(value) matches the strings length and value, and write theese possibilities to a new column.
At last even their sum of length and sum of values matches each other there can be some posibilities that doesnt match the whole string i will elliminate theese ones (Example; "doma-in" can be "moda-in" too and their lengths and values are same but not same words)
I dont know but,i guess with that value method i can solve the time proplem??? , or if there is another ways to do that, i will be gratefull taking your advices.
Thanks
You could try to find the solutions recursively by looking always at the next letter. For example for the word DOMAIN
D - no
DO - is a word!
M - no
MA - no
MAI - no
MAIN - is a word!
No more letters --> DO + MAIN
DOM - is a word!
A - no
AI - no
AIN - no
Finished without result
DOMA - no
DOMAI - no
DOMAIN - is a word!
No more letters --> DOMAIN

Problem with File IO and splitting strings with Environment.NewLine in VB.Net

I was experimenting with basic VB.Net File IO and String splitting. I encountered this problem. I don't know whether it has something to do with the File IO or String splitting.
I am writing text to a file like so
Dim sWriter As New StreamWriter("Data.txt")
sWriter.WriteLine("FirstItem")
sWriter.WriteLine("SecondItem")
sWriter.WriteLine("ThirdItem")
sWriter.Close()
Then, I am reading the text from the file
Dim sReader As New StreamReader("Data.txt")
Dim fileContents As String = sReader.ReadToEnd()
sReader.Close()
Now, I am splitting fileContents using Environment.NewLine as the delimiter.
Dim tempStr() As String = fileContents.Split(Environment.NewLine)
When I print the resulting Array, I get some weird results
For Each str As String In tempStr
Console.WriteLine("*" + str + "*")
Next
I added the *s to the beginning and end of the Array items during printing, to find out what is going on. Since NewLine is used as the delimiter, I expected the strings in the Array to NOT have any NewLine's. But the output was this -
*FirstItem*
*
SecondItem*
*
ThirdItem*
*
*
Shouldn't it be this -
*FirstItem*
*SecondItem*
*ThirdItem*
**
??
Why is there a new line in the beginning of all but the first string?
Update: I did a character by character print of fileContents and got this -
F - 70
i - 105
r - 114
s - 115
t - 116
I - 73
t - 116
e - 101
m - 109
- 13
- 10
S - 83
e - 101
c - 99
o - 111
n - 110
d - 100
I - 73
t - 116
e - 101
m - 109
- 13
- 10
T - 84
h - 104
i - 105
r - 114
d - 100
I - 73
t - 116
e - 101
m - 109
- 13
- 10
It seems 'Environment.NewLine' consists of
- 13
- 10
13 and 10.. I understand. But the empty space in between? I don't know whether it is coming due to printing to the console or is really a part of NewLine.
So, when splitting, only the character equivalent of ASCII value 13, which is the first character of NewLine, is used as delimiter (as explained in the replies) and the remaining stuff is still present in the strings. For some reason, the mysterious empty space in the list above and ASCII value 10 together result in a new line being printed.
Now it is clear. Thanks for the help. :)
First of all, yes, WriteLine tacks on a newline to the end of the string, hence the blank line at the end.
The problem is the way you're calling fileContents.Split(). The only version of that function that takes only one argument takes a char(), not a string. Environment.NewLine is a string, not a char, so (assuming you have Option Strict Off) when you're calling the function it's implicitly converting it to a char, using only the first character in the string. This means that instead of splitting your string on the actual sequence of two characters that make up Environment.NewLine, it's actually splitting only on the first of those characters.
To get your desired output, you need to call it like this:
Dim delims() as String = { Environment.NewLine }
Dim tempStr() As String = fileContents.Split(delims, _
StringSplitOptions.RemoveEmptyEntries)
This will cause it to split on the actual string, rather than the first character as it's doing now, and it will remove any blank entries from the results.
Why not just use File.ReadAllLines? One single call reads the file and returns a string array with the lines.
Dim tempStr() As String = File.ReadAllLines("data.txt")
I just ran into the same issue, and found all the comments very helpful. However, I corrected my issue by replacing "Environment.NewLine" with vbLF (as opposed to vbCrLf, which had the same issue). Any issues with this approach? (It seems more straight forward, but I'm not a programmer, so I wouldn't know of any potential issues).