can't understand offset member in program header and section header - c

I read man page. it says that
in ELF header:
e_phoff - This member holds the program header table's file offset in bytes.
e_shoff - This member holds the section header table's file offset in bytes.
In Program Header
p_offset This member holds the offset from the beginning of the file
at which the first byte of the segment resides.
In Section Header
sh_offset This member's value holds the byte offset from the beginning of the file to the first byte in the section
I'm confused. In my opinion, this means that in Elf header i can see offset to all program and section headers. And in the program header, i can see offset to the concrete segment in the file. In section header, i can see offset to the concrete section in the file. But it is not true. I found simple elf parse and i have seen this result
segment offset: 52
section offset: 6032
Program Entry point: 0x8048420
Section header list:
.interp: 0x8048154
offset: 340
.note.ABI-tag: 0x8048168
offset: 360
.note.gnu.build-id: 0x8048188
offset: 392
.gnu.hash: 0x80481ac
offset: 428
.dynsym: 0x80481e8
offset: 488
.dynstr: 0x80482b8
offset: 696
.gnu.version: 0x8048342
offset: 834
.gnu.version_r: 0x804835c
offset: 860
.rel.dyn: 0x804837c
offset: 892
.rel.plt: 0x8048394
offset: 916
.init: 0x80483ac
offset: 940
.plt: 0x80483d0
offset: 976
.plt.got: 0x8048410
offset: 1040
.text: 0x8048420
offset: 1056
.fini: 0x8048604
offset: 1540
.rodata: 0x8048618
offset: 1560
.eh_frame_hdr: 0x8048628
offset: 1576
.eh_frame: 0x8048664
offset: 1636
.init_array: 0x8049efc
offset: 3836
.fini_array: 0x8049f00
offset: 3840
.dynamic: 0x8049f04
offset: 3844
.got: 0x8049ff4
offset: 4084
.got.plt: 0x804a000
offset: 4096
.data: 0x804a018
offset: 4120
.bss: 0x804a020
offset: 4128
.comment: 0x0
offset: 4128
.symtab: 0x0
offset: 4172
.strtab: 0x0
offset: 5244
.shstrtab: 0x0
offset: 5768
Program header list
Phdr segment: 0x8048034
offset: 52
Interpreter: /lib/ld-linux.so.2
offset: 340
Text segment: 0x8048000
offset: 0
Data segment: 0x8049efc
offset: 3836
Dynamic segment: 0x8049f04
offset: 3844
Note segment: 0x8048168
offset: 360
PT_GNU_EH_FRAME: 0x8048628
offset: 1576
PT_GNU_STACK: 0x0
offset: 0
PT_GNU_RELRO: 0x8049efc
offset: 3836
As you can see Elf offset have section offset = 6032, but all sections offset less than Elf offset. Actually all sections in this program have offset like 6032 + (n * sizeof(Elf32_Shdr)). in this case, I can’t understand what does the offset in the section header mean? I thought, that it is offset in process image, but man page is talking about the offset inside the file. the same question about the offset in the program header. Please clarify what all the same mean section header offset and program header offset.
the parser is too large, so I did not attach it. But if someone needs it, I will do it

Actually all sections in this program have offset like 6032 + (n * sizeof(Elf32_Shdr)).
No, not all sections have this offsets, but all section entries of the section header table.
What you see is that the table is placed at a higher offset than the sections that are defined in its entries.
In your example:
At offset 1056 of the file starts the ".text" section.
At offset 6032 of the file starts the section header table. Its 14th entry (at 6032 + 13 * sizeof(Elf32_Shdr)) defines the ".text" section and gives its offset as 1056.

Related

U-boot 'nand markbad' has no effect

Situation : board with an Arm CPU that has Nand flash next to it. On power-up, U-boot bootloader starts up and copies the flash contents to RAM, then it transfers control to that code in RAM. A Linux system with some application code, composed through Buildroot, starts running. Its entire filesystem is stored as a single UBIFS file in flash, and it starts using that.
When a certain byte is set, the bootloader keeps in control, and starts a TFTP transfer to download and store a new flash image.
Trigger : a board came back defective. Linux kernel startup clearly shows the issue:
[ 1.931150] Creating 8 MTD partitions on "atmel_nand":
[ 1.936285] 0x000000000000-0x000000040000 : "at91bootstrap"
[ 1.945280] 0x000000040000-0x0000000c0000 : "bootloader"
[ 1.954065] 0x0000000c0000-0x000000100000 : "bootloader env"
[ 1.963262] 0x000000100000-0x000000140000 : "bootloader redundant env"
[ 1.973221] 0x000000140000-0x000000180000 : "spare"
[ 1.981552] 0x000000180000-0x000000200000 : "device tree"
[ 1.990466] 0x000000200000-0x000000800000 : "kernel"
[ 1.999210] 0x000000800000-0x000010000000 : "rootfs"
...
[ 4.016251] ubi0: attached mtd7 (name "rootfs", size 248 MiB)
[ 4.022181] ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 126976 bytes
[ 4.029040] ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 2048
[ 4.035941] ubi0: VID header offset: 2048 (aligned 2048), data offset: 4096
[ 4.042960] ubi0: good PEBs: 1980, bad PEBs: 4, corrupted PEBs: 0
[ 4.049033] ubi0: user volume: 2, internal volumes: 1, max. volumes count: 128
[ 4.056359] ubi0: max/mean erase counter: 2/0, WL threshold: 4096, image sequence number: 861993884
[ 4.065476] ubi0: available PEBs: 0, total reserved PEBs: 1980, PEBs reserved for bad PEB handling: 36
[ 4.074898] ubi0: background thread "ubi_bgt0d" started, PID 77
...
[ 4.298009] UBIFS (ubi0:0): UBIFS: mounted UBI device 0, volume 0, name "rootfs", R/O mode
[ 4.306415] UBIFS (ubi0:0): LEB size: 126976 bytes (124 KiB), min./max. I/O unit sizes: 2048 bytes/2048 bytes
[ 4.316418] UBIFS (ubi0:0): FS size: 155926528 bytes (148 MiB, 1228 LEBs), journal size 9023488 bytes (8 MiB, 72 LEBs)
[ 4.327197] UBIFS (ubi0:0): reserved for root: 0 bytes (0 KiB)
[ 4.333095] UBIFS (ubi0:0): media format: w4/r0 (latest is w5/r0), UUID AE9F77DC-04AF-433F-92BC-D3375C83B518, small LPT model
[ 4.346924] VFS: Mounted root (ubifs filesystem) readonly on device 0:15.
[ 4.356186] devtmpfs: mounted
[ 4.367038] Freeing unused kernel memory: 1024K
[ 4.371812] Run /sbin/init as init process
[ 4.568143] UBIFS (ubi0:1): background thread "ubifs_bgt0_1" started, PID 83
[ 4.644809] UBIFS (ubi0:1): recovery needed
[ 4.685823] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[ 4.732212] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[ 4.778705] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read only 126976 bytes, retry
[ 4.824159] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 235:4096, read 126976 bytes
... which causes an exception, but the kernel keeps on going, then another error is detected :
[ 5.071518] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[ 5.118110] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[ 5.164447] ubi0 warning: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read only 126976 bytes, retry
[ 5.210987] ubi0 error: ubi_io_read: error -74 (ECC error) while reading 126976 bytes from PEB 709:4096, read 126976 bytes
... but impressively, the system still comes up alive and behaves almost fine.
Why does the kernel not mark these flash blocks as bad ? Those data can't be read anyway, and at least the next image flashing might skip the bad blocks...
Investigation : so the Kernel found a defective PEB #235 (decimal) in the "rootfs" partition of the flash. Each PEB is 128KB, so the error sits somewhere beyond byte 30,801,920 (decimal). Since the "rootfs" partition only starts from byte 0x800000 of the flash, the actual damaged page must be somewhere beyond byte 39,190,528 (decimal) or 0x2560000. And sure enough, when using the nand read utility within U-boot :
U-Boot> nand read 0x20000000 0x2560000 0x1000
NAND read: device 0 offset 0x2560000, size 0x1000
4096 bytes read: OK
U-Boot> nand read 0x20000000 0x2561000 0x1000
NAND read: device 0 offset 0x2561000, size 0x1000
4096 bytes read: OK
U-Boot> nand read 0x20000000 0x2562000 0x1000
NAND read: device 0 offset 0x2562000, size 0x1000
PMECC: Too many errors
NAND read from offset 2562000 failed -5
0 bytes read: ERROR
so the damaged page sits at offset 8K within that block of flash.
From various other posts, I learned that nand flash with 2K pages organized in 128K blocks, has an extra 64 "Out Of Band" bytes over every 2048 payload bytes, bringing each page to a gross size of 2112 bytes. Anyway, the entire block of 128K will have to be disused, as this is the erase size. No problem, there is storage to spare, I just want to make sure that the next flashing will skip over this bad block.
Since neither the Linux kernel nor the bootloader bothered to mark the bad block, I'll do it by hand in U-boot:
U-Boot> nand markbad 2562000
block 0x02562000 successfully marked as bad
A similar investigation for the 2nd bad flash page reveals that the other error sits at flash address 0x60a1000 :
U-Boot> nand read 0 60A1000 800
NAND read: device 0 offset 0x60a1000, size 0x800
PMECC: Too many errors
NAND read from offset 60a1000 failed -5
0 bytes read: ERROR
so here too, the nand markbad utility is used to manually put a permanent mark on this block :
U-Boot> nand markbad 60a1000
block 0x060a1000 successfully marked as bad
and to verify that everything is taken into account :
U-Boot> nand bad
Device 0 bad blocks:
02560000
060a0000
Just like it should be - from the start of each 128K block, both blocks are marked.
Problem : so I learned that the 64 OOB bytes are divided in 2 bytes marker, 38 bytes error-correcting code, and 24 bytes journaling. Of all the OOB bytes accompanying each 2048 payload bytes, only the very first piece of 64 bytes, accompanying the first page of 2KB, lends its 2 bytes marker code to indicate the status of the entire 128KB block. These 2 bytes should be modified in the flash device itself so that this status is persistent. So in my U-boot session, instead of launching the Linux system, I restarted the CPU and remained in U-boot :
U-Boot> reset
resetting ...
RomBOOT
ba_offset = 0xc ...
AT91Bootstrap 3.6.0-00029-g0cd4e6a (Wed Nov 12 12:14:04 CET 2014)
NAND: ONFI flash detected
NAND: Manufacturer ID: 0x2c Chip ID: 0x32
NAND: Disable On-Die ECC
PMECC: page_size: 0x800, oob_size: 0x40, pmecc_cap: 0x4, sector_size: 0x200
NAND: Initialize PMECC params, cap: 0x4, sector: 0x200
NAND: Image: Copy 0x80000 bytes from 0x40000 to 0x26f00000
NAND: Done to load image
U-Boot 2013.10-00403-g1f9a20a (Nov 12 2014 - 12:14:27)
CPU: SAMA5D31
Crystal frequency: 12 MHz
CPU clock : 528 MHz
Master clock : 132 MHz
DRAM: 128 MiB
NAND: 256 MiB
MMC: mci: 0
In: serial
Out: serial
Err: serial
Net: macb0
Hit any key to stop autoboot: 0
U-Boot> nand info
Device 0: nand0, sector size 128 KiB
Page size 2048 b
OOB size 64 b
Erase size 131072 b
U-Boot> nand bad
Device 0 bad blocks:
U-Boot>
The bad blocks have been forgotten - the marker code was not applied persistently ?
Granted, this U-boot version seems rather old. Has the nand markbad utility been improved since then ?
Workaround : I modified the OOB bytes of the first page within the bad block myself. I read all 2112 bytes of the first page into RAM, then modified the 2 bytes marker code, and wrote the 2112 bytes back from RAM into flash. Technically, I should have erased the whole 128K flash page and then written back all 128K of contents. But my laziness has been challenged enough today. Nand flash can be toggled from 1 to 0 arbitrarily - it's the reverse operation that is hard, requiring an erase to restore a whole 128K page back to all-0xFF. I noticed that all the "block good" markers are encoded as 0xFFFF, so I figured that writing "0x0000" instead should suffice.
U-Boot> nand read.raw 0x20200000 0x2560000 1
NAND read: 2112 bytes read: OK
The format for nand read.raw is a bit quirky, as opposed to nand.read which expects size as the last argument in bytes, it wants size expressed in number-of-pages instead. The first page is all we need, so argument '1' does the trick. The contents, which have now been transferred to RAM, can be inspected with U-boot's md utility :
U-Boot> md 0x20200000 0x210
20200000: 23494255 00000001 00000000 01000000 UBI#............
20200010: 00080000 00100000 9cfb6033 00000000 ........3`......
...
202007e0: 00000000 00000000 00000000 00000000 ................
202007f0: 00000000 00000000 00000000 00000000 ................
20200800: ffffffff ffffffff ffffffff ffffffff ................
20200810: ffffffff ffffffff ffffffff ffffffff ................
20200820: ffffffff b0c9aa24 0008fdb8 00000000 ....$...........
20200830: 00000000 00000000 00000000 00000000 ................
Note how the md utility expects its size argument in yet a different format : this one expects it in units of words. Just to keep us alert.
The dump at address 0x20200800 clearly shows how markbad has failed its purpose: the 2 marker bytes of the bad block are still merrily on 0xFFFF.
Then to modify these bytes, another U-boot utility comes in handy :
U-Boot> mm 0x20200800
20200800: ffffffff ? 00000000
20200804: ffffffff ? q
It's a bit crude, I've changed the 4 first OOB bytes instead of just the 2 first marker bytes. Finall, to write the modified contents back into flash :
U-Boot> nand write.raw 0x20200000 0x2560000 1
NAND write: 2112 bytes written: OK
Funny enough, the nand bad diagnostic doesn't notice the block which has just been marked, even after some nand read attempts which do fail.
U-Boot> nand bad
Device 0 bad blocks:
U-Boot>
But this is no cause for alarm. The 2nd bad block was marked manually in a similar fashion, and upon another reset :
U-Boot> reset
resetting ...
RomBOOT
ba_offset = 0xc ...
AT91Bootstrap 3.6.0-00029-g0cd4e6a (Wed Nov 12 12:14:04 CET 2014)
...
U-Boot 2013.10-00403-g1f9a20a (Nov 12 2014 - 12:14:27)
...
Hit any key to stop autoboot: 0
U-Boot> nand bad
Device 0 bad blocks:
02560000
060a0000
U-Boot>
Lo and behold, the 'bad block' marking has persisted ! The next flash storage operation neatly skipped over the bad blocks, saving a consistent kernel and filesystem in the various partitions of the flash. This was the intention all along, but it seems to require gritty manual work. Is there no automated way ?
U-Boot has changed quite a bit since 2014. Patches possibly of relevance to your problem include:
dc0b69fa9f97 ("mtd: nand: mxs_nand: allow to enable BBT support")
c4adf9db5d38 ("spl: nand: sunxi: remove support for so-called 'syndrome' mode")
8d1809a96699 ("spl: nand: simple: replace readb() with chip specific read_buf()")
Please, retest with U-Boot Git HEAD. If there is still something missing, please, report it to the U-Boot developer list or even better send your patch.

Why are my libraries linked twice?

Take this gdb output for example:
(gdb) info proc mappings
process 3975
cmdline = '/mnt/hw6/rop-exploit'
cwd = '/mnt/hw6'
exe = '/mnt/hw6/rop-exploit'
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x8049000 0x1000 0 /mnt/hw6/rop-exploit
0x8049000 0x804a000 0x1000 0 /mnt/hw6/rop-exploit
0x804a000 0x806b000 0x21000 0x804a000 [heap]
0xb7d51000 0xb7e84000 0x133000 0 /lib/libc-2.7.so
0xb7e84000 0xb7e85000 0x1000 0x133000 /lib/libc-2.7.so
0xb7e85000 0xb7e87000 0x2000 0x134000 /lib/libc-2.7.so
0xb7e87000 0xb7e8b000 0x4000 0xb7e87000
0xb7e8b000 0xb7fd4000 0x149000 0 /lib/tls/i686/cmov/libc-2.7.so
0xb7fd4000 0xb7fd5000 0x1000 0x149000 /lib/tls/i686/cmov/libc-2.7.so
0xb7fd5000 0xb7fd7000 0x2000 0x14a000 /lib/tls/i686/cmov/libc-2.7.so
0xb7fd7000 0xb7fda000 0x3000 0xb7fd7000
0xb7fda000 0xb7fdc000 0x2000 0 /lib/tls/i686/cmov/libdl-2.7.so
0xb7fdc000 0xb7fde000 0x2000 0x1000 /lib/tls/i686/cmov/libdl-2.7.so
0xb7fe1000 0xb7fe3000 0x2000 0xb7fe1000
0xb7fe3000 0xb7fe4000 0x1000 0xb7fe3000 [vdso]
0xb7fe4000 0xb7ffe000 0x1a000 0 /lib/ld-2.7.so
0xb7ffe000 0xb8000000 0x2000 0x19000 /lib/ld-2.7.so
0xbffeb000 0xc0000000 0x15000 0xbffeb000 [stack]
(gdb) list
13 }
14
15 int main(int argc, char** argv) {
16 void* libc = dlopen("/lib/libc-2.7.so", RTLD_NOW);
17 void* address = dlsym( libc, "__libc_init_first");
18 printf("Address of <__libc_init_first>: %p\n", address);
19 if(argc > 1) {
20 foo(argv[1]);
21 }
22 printf("Done.\n");
(gdb) x libc
0x804a020: 0xb7d51000
(gdb) print address
$4 = (void *) 0xb7d672a0
You can see that three libraries are dynamically linked with the binary. libc-2.7, libc2-7.so (from a different location, maybe this is done automatically) and libdl-2.7.so
I dont understand why there are two to three entries in this list per library, I want to know what is going on there, and why they are separate entries.
I dont have any assumptions what is going on there and I dont know how I can explain any of this.
Take the first linked library for example:
The first section I assume is the library itself, it has the ELF header so I am convinced that it truly is the libc I have linked.
When I peek into the second entry of /lib/libc-2.7-so I just get lots of NULL bytes, dont know whats going on here.
(gdb) x/100x 0xb7e84000
0xb7e84000: 0x00000000 0x00000000 0x00000000 0x00000000
0xb7e84010: 0x00000000 0x00000000 0x00000000 0x00000000
0xb7e84020: 0x00000000 0x00000000 0x00000000 0x00000000
When I peek into the third entry of /lib/libc-2.6.so I get addresses to instructions (gadgets or functions maybe).
(gdb) x/100x 0xb7e85000
0xb7e85000: 0x0000006f 0xb7e671dc 0xb7e671e0 0xb7e671e4
0xb7e85010: 0xb7e671e8 0xb7e671ec 0xb7e671f0 0xb7e671f4
0xb7e85020: 0xb7e671f8 0xb7e671ff 0xb7e67206 0xb7e6720e
This is the example output I get from one of the addresses, seems pretty convincing that this could be usable code.
(gdb) x/10i 0xb7e671e8
0xb7e671e8: push %edi
0xb7e671e9: add %dl,%fs:%gs:0x75(%eax,%ebp,2)
0xb7e671ef: add %al,0x72(%esi)
0xb7e671f2: imul $0x746153,(%eax),%eax
0xb7e671f8: push %ebx
0xb7e671f9: jne 0xb7e67269
0xb7e671fb: fs
0xb7e671fc: popa
0xb7e671fd: jns 0xb7e671ff
0xb7e671ff: dec %ebp
(gdb)
My questions are, what are these three sections doing each ? Why are they split up like that ? What happens in the area where no corresponding label exists but is still mapped ?

Executable Packer (decompression/decryption stub)

I am working on an executable Packer & I have done compression & Encryption part so far. Now I have to store decompression/decryption stub/routine in the compressed file. My question is that will this stub be written in HEX code or I can place the assembly instruction directly ? If later is possible, then how ?
Creating a working packed binary requires:
modify the PE geometry
insert your code
Depending on your code size, you might want to use section padding, or to add your own section.
Then, to insert your code - as you seem to prefer direct ASM insertion - my suggestion would be to make the decryption code EIP-independent, then assemble it with something like YASM as pure code (-o), and include the code as assembled binary directly.
I wrote several mini-packers that might help as a starting reference, as they also 'insert' assembled code.
You have to have section with characteristic as "readable" & "writable" & "contains code" & "Is executable"
Address of Entry Point: 0x00019860
Section Header #1
Name: UPX0
Virtual Size: 0x00010000 (65536)
Virtual Address: 0x00001000
Size of Raw Data: 0x00000000 (0)
File Pointer to Raw Data: 0x00000400
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xE0000080
Section contains uninitialized data.
Section is executable.
Section is readable.
Section is writeable.
Section Header #2
Name: UPX1
Virtual Size: 0x00009000 (36864)
Virtual Address: 0x00011000
Size of Raw Data: 0x00008A00 (35328)
File Pointer to Raw Data: 0x00000400
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xE0000040
Section contains initialized data.
Section is executable.
Section is readable.
Section is writeable.
Section Header #3
Name: .rsrc
Virtual Size: 0x00001000 (4096)
Virtual Address: 0x0001A000
Size of Raw Data: 0x00000800 (2048)
File Pointer to Raw Data: 0x00008E00
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xC0000040
Section contains initialized data.
Section is readable.
Section is writeable.
Just in short, UPX generates one section which contains compressed code and decompressor routine and second section which is uninitialized but is allowed to have writable and executable characteristic. The decompressor routine decompresses the code to the uninitialized section and continues with execution of the original entrypoint...

How to make the arm linker decompress the second correctly with "RW data compression"?

title: How to make the arm linker decompress the second load region while both 1st and 2nd region are applied "RW data compression"?
I got a below scatter file (a simple version of my complex scatter file)
LOAD_REGION_01 0x0
{
EXECUTION_REGION_01 0x0
{
ABC.o (+RO,+RW)
}
}
LOAD_REGION_02 +0x0
{
EXECUTION_REGION_02 0x100
{
DEF.o (+RO,+RW)
}
}
The RW data compression is applied automatically and I got a binary with size 0x40 (0x20 for LOAD_REGION_01 and 0x20 for LOAD_REGION_02 ), the got a link.info as following MAP file.
Load Region LOAD_REGION_01 (Base: 0x0, Size: 0x30, Max: 0x000000a0, ABSOLUTE)
Execution Region EXECUTION_REGION_01 (Base:0x0,Size:0x30,Max:0xffffffff,ABSOLUTE, COMPRESSED[0x20])
Load Region LOAD_REGION_02 (Base: 0x30, Size: 0x30, Max: 0x000000a0, ABSOLUTE)
Execution Region EXECUTION_REGION_02 (Base:0x0,Size:0x30,Max:0xffffffff,ABSOLUTE, COMPRESSED[0x20])
I found that the size of load region after compression is 0x20, but the start address of second load region is 0x30 ! And, the decompression of first region work correctly, but arm try to decompress the second region from address "0x30" not "0x20".
Therefore, a wrong decompression result is produced. How to make the arm linker decompress the second correctly? Or how can I assign the load address of second load region LOAD_REGION_02 with attribute +0 (since the size load region 1 may changed...) ?
I read all the user manual but no answer...
It seems your issue is that both load regions are declared to start at address 0.
From a quick read of the ARM doc I see two options to resolve it:
Use one load region and two exec regions:
LOAD_REGION_01 0x0
{
EXECUTION_REGION_01 0x0
{
ABC.o (+RO,+RW)
}
EXECUTION_REGION_02 0x100
{
DEF.o (+RO,+RW)
}
}
Use two load regions with non-overlapping addresses. +0 should work if I'm reading it correctly.
LOAD_REGION_01 0x0
{
EXECUTION_REGION_01 0x0
{
ABC.o (+RO,+RW)
}
}
LOAD_REGION_02 +0
{
EXECUTION_REGION_02 0x100
{
DEF.o (+RO,+RW)
}
}

How to find the address of a string in memory using GDB?

I want to find the address of a string in memory. In this case, I'm looking for "/bin/sh". Its an initialized variable, so its in the .data section and after compilation, it has a fixed address. So what do I do in GDB to find out its memory address? And I do not know the name of the variable its stored in.
Using info proc map sounds like a better approach to me.
(gdb) info proc map
process 930
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x401000 0x1000 0x0 /myapp
0x600000 0x601000 0x1000 0x0 /myapp
0x601000 0x602000 0x1000 0x1000 /myapp
0x7ffff7a1c000 0x7ffff7bd2000 0x1b6000 0x0 /usr/lib64/libc-2.17.so
0x7ffff7bd2000 0x7ffff7dd2000 0x200000 0x1b6000 /usr/lib64/libc-2.17.so
0x7ffff7dd2000 0x7ffff7dd6000 0x4000 0x1b6000 /usr/lib64/libc-2.17.so
0x7ffff7dd6000 0x7ffff7dd8000 0x2000 0x1ba000 /usr/lib64/libc-2.17.so
(gdb) find 0x7ffff7a1c000,0x7ffff7bd2000,"/bin/sh"
0x7ffff7b98489
1 pattern found.
(gdb) x /s 0x7ffff7b98489
0x7ffff7b98489: "/bin/sh"
(gdb) x /xg 0x7ffff7b98489
0x7ffff7b98489: 0x0068732f6e69622f
If you want to search in the whole address space of the process, you need to get the memory mapping for your process and use the start address the end address with the find command in gdb.for instance, if cat /proc/$PID/maps shows that your process's virtual memory ranges from 0x08048000 to 0xc0000000 you can search as follows:
(gdb) find 0x80048000, 0xc0000000, "/bin/sh"
Another way to get the memory mapping of your process is using the gdb's embedded command :
(gdb) info proc map
Use the find command.
find [/sn] start_addr, +len, val1 [, val2, …]
find [/sn] start_addr, end_addr, val1 [, val2, …]
Search memory for the sequence of bytes specified by val1, val2, etc.
The search begins at address start_addr and continues for either len
bytes or through to end_addr inclusive.
s and n are optional parameters. They may be specified in either
order, apart or together.
s, search query size The size of each search query value.
b bytes
h halfwords (two bytes)
w words (four bytes)
g giant words (eight bytes)
All values are interpreted in the current language. This means, for
example, that if the current source language is C/C++ then searching
for the string “hello” includes the trailing ’\0’.
If the value size is not specified, it is taken from the value’s type
in the current language. This is useful when one wants to specify the
search pattern as a mixture of types. Note that this means, for
example, that in the case of C-like languages a search for an untyped
0x42 will search for ‘(int) 0x42’ which is typically four bytes.
n, maximum number of finds The maximum number of matches to print. The
default is to print all finds.
You can use strings as search values. Quote them with double-quotes
("). The string value is copied into the search pattern byte by byte,
regardless of the endianness of the target and the size specification.
The address of each match found is printed as well as a count of the
number of matches found.
The address of the last value found is stored in convenience variable
‘$_’. A count of the number of matches is stored in ‘$numfound’.
Take this example:
1.find the string "Can not open script" .
2.gdb>info proc map
process 8636
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x8898000 0x850000 0x0 /home/lela/ask/mLinux32
0x8898000 0x8902000 0x6a000 0x850000 /home/lela/ask/mLinux32
0x8902000 0x8d4c000 0x44a000 0x0 [heap]
0xf6800000 0xf6821000 0x21000 0x0
0xf6821000 0xf6900000 0xdf000 0x0
0xf6a00000 0xf6a21000 0x21000 0x0
0xf6a21000 0xf6b00000 0xdf000 0x0
0xf6b00000 0xf6b21000 0x21000 0x0
0xf6b21000 0xf6c00000 0xdf000 0x0
0xf6cbf000 0xf6cc0000 0x1000 0x0
0xf6cc0000 0xf6d00000 0x40000 0x0
0xf6d00000 0xf6d21000 0x21000 0x0
0xf6d21000 0xf6e00000 0xdf000 0x0
0xf6e06000 0xf6e07000 0x1000 0x0
0xf6e07000 0xf6e47000 0x40000 0x0
0xf6e47000 0xf6e48000 0x1000 0x0
0xf6e48000 0xf6e88000 0x40000 0x0
0xf6e88000 0xf6e89000 0x1000 0x0
0xf6e89000 0xf794f000 0xac6000 0x0
0xf794f000 0xf7a4f000 0x100000 0x0
0xf7a4f000 0xf7c15000 0x1c6000 0x0
0xf7c15000 0xf7c17000 0x2000 0x0 /usr/lib/i386-linux-gnu/libgcc_s.so.1
0xf7c17000 0xf7c2d000 0x16000 0x2000 /usr/lib/i386-linux-gnu/libgcc_s.so.1
0xf7c2d000 0xf7c32000 0x5000 0x18000 /usr/lib/i386-linux-gnu/libgcc_s.so.1
0xf7c32000 0xf7c33000 0x1000 0x1c000 /usr/lib/i386-linux-gnu/libgcc_s.so.1
like this result.
3.use find command with the start address and end address,and string with string type length ex:{char[19]},likes below.
gdb➤ find 0x8048000, 0x8902000, {char[19]}"Can not open script"
0x8611234
1 pattern found.
gdb➤ x/s 0x8611234
0x8611234: "Can not open script file \"%s\" to execute.\n"
4.finish.

Resources