How to get the .plt address when i have the GOT_OFFSET_TABLE? - reverse-engineering

When I test to reconstruct the elf executable from process image, i got the .dynamic and GOT_OFFSET_TABLE,but The global offset table was filled in with the resolved values of the corresponding shared library functions.I must replace these addresses with the original PLT stub addresses. So,how can I get the PLT stub addresses from a process image.
for(c=0;dyn[c].d_tag !=DT_NULL ;c++){
switch (dyn[c].d_tag){
case DT_PLTGOT:
got = (Elf64_Addr)dyn[c].d_un.d_ptr;
printf("[+]Located plt.got vaddr:0x%x\n",got);
printf("[+]Relevant GOT entries begin at 0x%x\n", (Elf64_Addr)dyn[c].d_un.d_ptr + 24);
got_off = dyn[c].d_un.d_ptr - h.data_vaddr;
GOT_TABLE = (Elf64_Addr*)&pmem[h.data_offset +got_off];
GOT_TABLE += 3;
break;
...
}
Elf64_Addr PLT_VADDR = ?
gdb-peda$ x/10gx 0x601000 + 3*8
0x601018: 0x00007f3eaf557800 0x00007f3eaf522740 0x601018->GOT_OFFSET_TABLE[3]
0x601028: 0x00007f3eaf578160 0x0000000000000000
0x601038: 0x0000000000000000 0x0000000000000000
0x601048: 0x0000000000000000 0x0000000000000000
0x601058: 0x0000000000000000 0x0000000000000000

Looks like we're reading the same book, 'Learning Linux Binary Analysis' and stuck on the same exercise. I did not find an elegant way to retrieve the .plt address but you may be able to find it by using ElfN_Shdr.sh_name and by doing a strcmp(ElfN_Shdr.sh_name, '.plt') on it.
The author, elfmaster seems to be using that :
https://github.com/elfmaster/ftrace/blob/master/ftrace.c#L418

So I managed do get my way out to .plt address on a stripped binary compiled with PIE(Process Independent Execution). I observed that the .plt section was always on top of .text section.
By substracting the rel relocation table size, stored in DT_RELSZ, to the entry point, e_entry, you can get the address of .plt. I do not know yet if it coincidence and that this trick is actually garbage but it works.
I checked multiples elfparser and it seems that they are all using section name(sh_name) to identify .plt section. We're asked to recover an ELF file in memory and it appears that section headers are only relevant for linking and not loaded for execution but I'm not sure and you should double checked that.

Related

How to edit a binary at specific address locations using Nim?

I'm trying to understand how to modify a Windows executable using Nim to write NOPs in specific locations of the file. In Python I do this as follows:
with open('file.exe', 'r+b') as f:
f.seek(0x0014bc0f)
f.write(binascii.unhexlify('9090'))
f.seek(0x0014bc18)
f.write(binascii.unhexlify('9090'))
But in Nim I can't find the necessary methods to accomplish the seeking to a specific address and how to input these op-codes properly. I'm pretty new to Nim and the different file operation possibilities are a little confusing.
the docs for io are quite good, but to start you off:
opening a file for reading and writing (equivalent of 'r+') is:
let f = open("file.exe",fmReadWriteExisting)
the equivalent of with here, to make sure to close the file on any error:
defer: f.close
seeking to an offset (by default bytes relative to the start):
f.setFilePos(0x014bc0f)
writing two bytes at that position (nop nop)
f.write("\x90\x90")
check out the documentation for each proc for more options

Use libpcap to capture multiple interfaces to same file

I would like to use libpcap to capture on multiple specific interfaces (not 'any') to the same file
I have the following code (error handling and some args removed):
static gpointer pkt_tracing_thread(gpointer data)
{
while (1)
{
pcap_dispatch(g_capture_device1, .., dump_file1);
pcap_dispatch(g_capture_device2, .., dump_file2);
}
}
fp1 = calloc(1, sizeof(struct bpf_program));
fp2 = calloc(1, sizeof(struct bpf_program));
cap_dev1 = pcap_open_live(interface1,...
cap_dev2 = pcap_open_live(interface2,...
pcap_compile(cap_dev1, fp1, ...
pcap_compile(cap_dev2, fp2, ...
pcap_setfilter(cap_dev1, fp1);
pcap_setfilter(cap_dev2, fp2);
dump_file1 = pcap_dump_open(g_capture_device1, filename);
dump_file2 = pcap_dump_open(g_capture_device2, filename);
g_thread_create_full(pkt_tracing_thread, (gpointer)fp1, ...
g_thread_create_full(pkt_tracing_thread, (gpointer)fp2, ...
This does not work. What I see in filename is just packets on one of the interfaces. I'm guessing there could be threading issues in the above code.
I've read https://seclists.org/tcpdump/2012/q2/18 but I'm still not clear.
I've read that libpcap does not support writing in pcapng format, which would be required for the above to work, although I'm not clear about why.
Is there any way to capture multiple interfaces and write them to the same file?
Is there any way to capture multiple interfaces and write them to the same file?
Yes, but 1) you have to open the output file only once, with one call to pcap_dump_open() (otherwise, as with your program, you may have two threads writing to the same file independently and stepping on each other) and 2) you would need to have some form of mutex to prevent both threads from writing to the file at the same time.
Also, you should have one thread reading only from one capture device and the other thread reading from the other capture device, rather than having both threads reading from both devices.
As user9065877, you have to open the output file only once and write to it only from one thread at a time.
However, since you'd be serializing everything anyway, you may prefer to ask libpcap for pollable file descriptors for the interfaces and poll in a round-robin fashion for packets, using a single thread and no mutexes.

Redacted comments in MS's source code for .NET [duplicate]

The Reference Source page for stringbuilder.cs has this comment in the ToString method:
if (chunk.m_ChunkLength > 0)
{
// Copy these into local variables so that they
// are stable even in the presence of ----s (hackers might do this)
char[] sourceArray = chunk.m_ChunkChars;
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
What does this mean? Is ----s something a malicious user might insert into a string to be formatted?
The source code for the published Reference Source is pushed through a filter that removes objectionable content from the source. Verboten words are one, Microsoft programmers use profanity in their comments. So are the names of devs, Microsoft wants to hide their identity. Such a word or name is substituted by dashes.
In this case you can tell what used to be there from the CoreCLR, the open-sourced version of the .NET Framework. It is a verboten word:
// Copy these into local variables so that they are stable even in the presence of race conditions
Which was hand-edited from the original that you looked at before being submitted to Github, Microsoft also doesn't want to accuse their customers of being hackers, it originally said races, thus turning into ----s :)
In the CoreCLR repository you have a fuller quote:
Copy these into local variables so that they are stable even in the presence of race conditions
Github
Basically: it's a threading consideration.
In addition to the great answer by #Jeroen, this is more than just a threading consideration. It's to prevent someone from intentionally creating a race condition and causing a buffer overflow in that manner. Later in the code, the length of that local variable is checked. If the code were to check the length of the accessible variable instead, it could have changed on a different thread between the time length was checked and wstrcpy was called:
// Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
///
/// imagine that another thread has changed the chunk.m_ChunkChars array here!
/// we're now in big trouble, our attempt to prevent a buffer overflow has been thawrted!
/// oh wait, we're ok, because we're using a local variable that the other thread can't access anyway.
fixed (char* sourcePtr = sourceArray)
string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
}
else
{
throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
}
chunk = chunk.m_ChunkPrevious;
} while (chunk != null);
Really interesting question though.
Don't think that this is the case - the code in question copies to local variables to prevent bad things happening if the string builder instance is mutated on another thread.
I think the ---- may relate to a four letter swear word...

Processing ELF relocations - understanding the relocs, symbols, section data, and how they work together

TL;DR
I tried to make this a short question but it's a complicated problem so it ended up being long. If you can answer any part of this or give any suggestions or tips or resources or anything at all, it would be extremely helpful (even if you don't directly solve all my issues). I'm banging my head against the wall right now. :)
Here are the specific issues I am having. Read on below for more information.
I'm looking for guidance on how to process relocation entries and update the unresolved symbols in the section data. I simply don't understand what to do with all the information I've pulled from the relocations and the sections, etc.
I'm also hoping to understand just what is going on when the linker encounters relocations. Trying to correctly implement the relocation equations and use all the correct values in the correct way is incredibly challenging.
When I encounter op codes and addresses and symbols, etc, I need to understand what to do with them. I feel like I am missing some steps.
I feel like I don't have a good grasp on how the symbol table entries interact with the relocations. How should I use the symbol's binding, visibility, value, and size information?
Lastly, when I output my file with the resolved data and new relocation entries used by the executable, the data is all incorrect. I'm not sure how to follow all the relocations and provide all the information necessary. What is the executable expecting from me?
My approach so far
I am trying to create a relocation file in a specific [undocumented] proprietary format that is heavily based on ELF. I have written a tool that takes an ELF file and a partially linked file (PLF) and processes them to output the fully resolved rel file. This rel file is used to load/unload data as needed in order to save memory. The platform is a 32bit PPC. One wrinkle is that tool is written for Windows in c#, but the data is intended for the PPC, so there are fun endian issues and the like to watch out for.
I've been trying to understand how relocations are handled when used to resolve unresolved symbols and so on. What I've done so far is to copy the relevant sections from the PLF and then for each corresponding .rela section, I parse the entries and attempt to fix up the section data and generate new relocation entries as needed. But this is where my difficulty is. I'm way out of my element here and this sort of thing seems to typically be done by linkers and loaders so there's not a lot of good examples to draw upon. But I have found a few that have been of help, including THIS ONE.
So what is happening is:
Copy section data from PLF to be used for rel file. I'm only interested in the .init (no data), .text, .ctors, .dtors, .rodata, .data, .bss (no data), and another custom section we are using.
Iterate over the .rela sections in the PLF and read in the Elf32_Rela entries.
For each entry, I pull out the r_offset, r_info, and r_addend fields and extract the relevant info from r_info (the symbol and the reloc type).
From the PLF's symbol table, I can get the symbolOffset, the symbolSection, and the symbolValue.
From the ELF, I get the symbolSection's load address.
I compute int localAddress = ( .relaSection.Offset + r_offset ).
I get the uint relocValue from the symbolSection's contents at r_offset.
Now I have all the info I need so I do a switch on the reloc type and process the data. These are the types I support:
R_PPC_NONE
R_PPC_ADDR32
R_PPC_ADDR24
R_PPC_ADDR16
R_PPC_ADDR16_LO
R_PPC_ADDR16_HI
R_PPC_ADDR16_HA
R_PPC_ADDR14
R_PPC_ADDR14_BRTAKEN
R_PPC_ADDR14_BRNTAKEN
R_PPC_REL24
R_PPC_REL14
R_PPC_REL14_BRTAKEN
R_PPC_REL14_BRNTAKEN
Now what?? I need to update the section data and build companion relocation entries. But I don't understand what is necessary to do and how to do it.
The whole reason I'm doing this is because there is an old obsolete unsupported tool that does not support using custom sections, which is a key requirement for this project (for memory reasons). We have a custom section that contains a bunch of initialization code (totaling about a meg) that we want to unload after start up. The existing tool just ignores all the data in that section.
So while making our own tool that does support custom sections is ideal, if there are any bright ideas for another way to achieve this goal, I'm all ears! We've floated around an idea of using the .dtor section for our data since it's nearly empty anyway. But this is messy and might not work anyway if it prevents a clean shutdown.
Relocations plus example code
When I process the relocations, I'm working off of the equations and information found in the ABI docs HERE (around section 4.13, page 80ish) as well as a number of other code examples and blog posts I've dug up. But it's all so confusing and not really spelled out and all the code I've found does things a little differently.
For example,
R_PPC_ADDR16_LO --> half16: #lo(S + A)
R_PPC_ADDR14_BRTAKEN --> low14*: (S + A) >> 2
etc
So when I see this kind of code, how do I decipher it?
Here's one example (from this source)
case ELF::R_PPC64_ADDR14 : {
assert(((Value + Addend) & 3) == 0);
// Preserve the AA/LK bits in the branch instruction
uint8_t aalk = *(LocalAddress+3);
writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));
} break;
case ELF::R_PPC64_REL24 : {
uint64_t FinalAddress = (Section.LoadAddress + Offset);
int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
if (SignExtend32<24>(delta) != delta)
llvm_unreachable("Relocation R_PPC64_REL24 overflow");
// Generates a 'bl <address>' instruction
writeInt32BE(LocalAddress, 0x48000001 | (delta & 0x03FFFFFC));
} break;
Here's some from another example (here)
case R_PPC_ADDR32: /* word32 S + A */
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
addr += addend;
*where = addr;
break;
case R_PPC_ADDR16_LO: /* #lo(S) */
if (addend != 0) {
addr = relocbase + addend;
} else {
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
}
*hwhere = addr & 0xffff;
break;
case R_PPC_ADDR16_HA: /* #ha(S) */
if (addend != 0) {
addr = relocbase + addend;
} else {
addr = elf_lookup(lf, symidx, 1);
if (addr == 0)
return -1;
}
*hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) & 0xffff;
break;
And one other example (from here)
case R_PPC_ADDR16_HA:
write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16);
break;
case R_PPC_ADDR24:
write_be32 (dso, rela->r_offset, (value & 0x03fffffc) | (read_ube32 (dso, rela->r_offset) & 0xfc000003));
break;
case R_PPC_ADDR14:
write_be32 (dso, rela->r_offset, (value & 0xfffc) | (read_ube32 (dso, rela->r_offset) & 0xffff0003));
break;
case R_PPC_ADDR14_BRTAKEN:
case R_PPC_ADDR14_BRNTAKEN:
write_be32 (dso, rela->r_offset, (value & 0xfffc)
| (read_ube32 (dso, rela->r_offset) & 0xffdf0003)
| ((((GELF_R_TYPE (rela->r_info) == R_PPC_ADDR14_BRTAKEN) << 21)
^ (value >> 10)) & 0x00200000));
break;
case R_PPC_REL24:
write_be32 (dso, rela->r_offset, ((value - rela->r_offset) & 0x03fffffc) | (read_ube32 (dso, rela->r_offset) & 0xfc000003));
break;
case R_PPC_REL32:
write_be32 (dso, rela->r_offset, value - rela->r_offset);
break;
I really want to understand the magic these guys are doing here and why their code doesn't always look the same. I think some of the code is making assumptions that the data was already properly masked (for branches, etc), and some of the code is not. But I don't understand any of this at all.
Following the symbols/data/relocations, etc
When I look at the data in a hexeditor, I see a bunch of "48 00 00 01" all over. I've figured out that this is an opcode and needs to be updated with relocation information (this specifically is for 'bl' branch and link), yet my tool doesn't operate on the vast majority of them and the ones that I do update have the wrong values in them (compared to an example made by an obsolete tool). Clearly I am missing some part of the process.
In addition to the section data, there are additional relocation entries that need to be added to the end of the rel file. These consist of internal and external relocations but I haven't figured out much at all about these yet. (what's the difference between the two and when do you use one or the other?)
If you look near the end of this file at the function RuntimeDyldELF::processRelocationRef, you'll see some Relocation Entries being created. They also make stub functions. I suspect this is the missing link for me, but it's as clear as mud and I'm not following it even a little bit.
When I output the symbols in each relocation entry, they each have a binding/visibility [Global/Weak/Local] [Function/Object] and a value, a size, and a section. I know the section is where the symbol is located, and the value is the offset to the symbol in that section (or is it the virtual address?). The size is the size of the symbol, but is this important? Maybe the global/weak/local is useful for determining if it's an internal or external relocation?
Maybe this relocation table I'm talking about creating is actually a symbol table for my rel file? Maybe this table updates the symbol value from being a virtual address to being a section offset (since that's what the value is in relocatable files and the symbol table in the PLF is basically in an executable)?
Some resources:
blog on relocations: http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/
mentions opcodes at the end: http://wiki.netbsd.org/examples/elf_executables_for_powerpc/
my related unanswered question: ELF Relocation reverse engineering
Whew! That's a beast of a question. Congrats if you made it this far. :) Thanks in advance for any help you can give me.
I stumbled across this question and thought it deserved an answer.
Have elf.h handy. You can find it on the internet.
Each RELA section contains an array of Elf32_Rela entries as you know, but is also tied to a certain other section. r_offset is an offset into that other section (in this case - it works differently for shared libraries). You will find that section headers have a member called sh_info. This tells you which section that is. (It's an index into the section header table as you would expect.)
The 'symbol', which you got from r_info is in fact an index into a symbol table residing in another section. Look for the member sh_link in your RELA section's header.
The symbol table tells you the name of the symbol you are looking for, in the form of the st_name member of Elf32_Sym. st_name is an offset into a string section. Which section that is, you get from the sh_link member of your symbol table's section header. Sorry if this gets confusing.
Elf32_Shdr *sh_table = elf_image + ((Elf32_Ehdr *)elf_image)->e_shoff;
Elf32_Rela *relocs = elf_image + sh_table[relocation_section_index]->sh_offset;
unsigned section_to_modify_index = sh_table[relocation_section_index].sh_info;
char *to_modify = elf_image + sh_table[section_to_modify_index].sh_offset;
unsigned symbol_table_index = sh_table[relocation_section_index].sh_link;
Elf32_Sym *symbol_table = elf_image + sh_table[symbol_table_index].sh_offset;
unsigned string_table_index = sh_table[symbol_table].sh_link;
char *string_table = elf_image + sh_table[string_table_index].sh_offset;
Let's say we are working with relocation number i.
Elf32_Rela *rel = &relocs[i];
Elf32_Sym *sym = &symbol_table[ELF32_R_SYM(rel->r_info)];
char *symbol_name = string_table + sym->st_name;
Find the address of that symbol (let's say that symbol_name == "printf"). The final value will go in (to_modify + rel->r_offset).
As for the table on pages 79-83 of the pdf you linked, it tells us what to put at that address, and how many bytes to write. Obviously the address we just got (of printf in this case) is part of most of them. It corresponds to the S in the expressions.
r_addend is just A. Sometimes the compiler needs to add a static constant to a reloc i guess.
B is the base address of the shared object, or 0 for executable programs because they are not moved.
So if ELF32_R_TYPE(rel->r_info) == R_PPC_ADDR32 we have S + A, and the word size is word32 so we would get:
*(uint32_t *)(to_modify + rel->r_offset) = address_of_printf + rel->r_addend;
...and we have successfully performed a relocation.
I can't help you when it comes to the #lo, #hi, etc and the word sizes like low14. I know nothing about PPC but the linked pdf seems reasonable enough.
I also don't know about the stub functions. You don't normally need to know about those when linking (dynamically at least).
I'm not sure if I've answered all of your questions but you should be able to see what your example code does now at least.
Just answering the question: What is relocation?
When you write assembly program, if it is position-dependent, the program will be assumed to be loaded in a specific part of memory. And when you load your program to another memory address, then all the memory relative addressing data will have to be updated so that it will load correctly from the new memory area.
For example:
load A, B
Sometimes B can be an address, sometimes it is just pure constant data. So only compiler will know when they generate the assembly. Compiler will construct a table of all entries containing the offset, and its original loading relative address, assuming a fixed global address where it is laded. This is called the relocation table.
It is linked to the symbol table, PLT table, and GOT etc:
http://blog.k3170makan.com/2018/10/introduction-to-elf-format-part-vi_18.html
https://reverseengineering.stackexchange.com/questions/1992/what-is-plt-got
What does the concept of relocation mean?
How does C++ linking work in practice?
Try to llok into ELF Specification. It takes about 60 pages, and greatly clarifies things. Especially part 2, the one about linking.

An exported aliases symbol doesn't exist in PDB file (RegisterClipboardFormat has RegisterWindowMessage internal name)

I'm trying to set a breakpoint in user32!RegisterClipboardFormat
Evidently, this function is exported (link /dump /exports - it is right there). Before downloading the PDB file from the Microsoft symbol server, I'm able to find this function:
0:001> lm m user32
start end
76eb0000 76fcf000 USER32 (export symbols) c:\Windows\system32\USER32.dll
0:001> x user32!RegisterClipboardFormat*
76ec4eae USER32!RegisterClipboardFormatA (<no parameter info>)
76ec6ffa USER32!RegisterClipboardFormatW (<no parameter info>)
No problems. I'm able to 'bu' any of these functions. But when I download the PDB symbols from the Microsoft PDB server:
0:001>
start end module name
76d50000 76e6f000 USER32 (pdb symbols) c:\symbols\user32.pdb\561A146545614951BDB6282F2E3522F72\user32.pdb
0:000> x user32!RegisterClipboardFormat
WinDBG cannot find the symbols. However, it can find RegisterWindowMesssage:
0:000> x user32!RegisterWindowMessage*
76d64eae USER32!RegisterWindowMessageA = <no type information>
76d66ffa USER32!RegisterWindowMessageW = <no type information>
Note that the functions have the same addresses (This is on Windows 8. Not sure about previous versions). This is probably achieved by the optimizer or in the DEF file (func1=func2 in the EXPORT section). 'link /dump /exports' shows RegisterWindowMessage and RegisterClipboardFormat have the same RVA.
Problem is that I spent way too much time on this. So my questions are:
Is there is an easy way, from within WinDBG to find out missing aliased export symbols.
Say I want to break only on RegisterClipboardFormatW. If I recall correctly, there should be a JMP instruction somewhere (in the calling module import table). How do I find that symbol? Is there a way to find this entry in all calling modules?
Since RegisterWindowMessage and RegisterClipboardFormat have the same RVA, they share the same implementation. Apparently Windows does not make any distinction between the two and both clipboard format and window messages share the same domain of identifiers.
For your first question -- how to find out which implementation function corresponds to exported function. (assuming you have symbols fixed up) First figure out RVA of the export:
C:\>link /dump /exports C:\Windows\Syswow64\user32.dll |findstr RegisterClipboardFormat
2104 24F 00020AFA RegisterClipboardFormatA
2105 250 00019EBD RegisterClipboardFormatW
Then in WinDbg find starting address where DLL is loaded from. Commands lm or lml list all modules, you just need to find the module you are after:
0:001> lml
start end module name
75460000 75560000 USER32
Using RVA as offset to the starting address, get symbol that corresponds to it:
0:002> ln 75460000+00020AFA
(75480afa) USER32!RegisterWindowMessageA | (75480b4a) USER32!MsgWaitForMultipleObjects
Exact matches:
0:002> ln 75460000+00019EBD
(75479ebd) USER32!RegisterWindowMessageW | (75479eea) USER32!NtUserGetProcessWindowStation
Exact matches:
So here we actually found out that RegisterClipboardFormat actually calls into RegisterWindowMessage.
Your second question -- how to put breakpoint only on RegisterClipboardFormat, and not on RegisterWindowMessage. In general it is impossible, because they share the same implementation. For example, your app might call GetProcAddress("RegisterClipboardFormat") and you will have hard time figuring out if it called to one function or another. However if you know that the call was made through imported function, then you can do this. All imported functions are declared in import address table in your application. If you put an access breakpoint on the entry in import address table, you can break before the call is made. This might be compiler specific, but I know that Visual C++ assigns symbolic names to entries in import address table. In this case putting breakpoint is easy:
ba r4 MyModule!_imp_RegisterClipboardFormatA