how to disassemble a system call? - linux

How could I disassemble system call, so that i could get the assembly instructions involved in it

Well, you could do something like this. Say I wanted to get an assembly dump of "dup":
Write this:
#include <stdio.h>
#include <sys/file.h>
int main() {
return dup(0)
}
Compile it:
gcc -o systest -g3 -O0 systest.c
Dump it:
objdump -d systest
Looking in "main" I see:
400478: 55 push %rbp
400479: 48 89 e5 mov %rsp,%rbp
40047c: bf 00 00 00 00 mov $0x0,%edi
400481: b8 00 00 00 00 mov $0x0,%eax
400486: e8 1d ff ff ff callq 4003a8 <dup#plt>
40048b: c9 leaveq
40048c: c3 retq
40048d: 90 nop
40048e: 90 nop
40048f: 90 nop
So looking at "dup#plt" I see:
00000000004003a8 <dup#plt>:
4003a8: ff 25 7a 04 20 00 jmpq *2098298(%rip) # 600828 <_GLOBAL_OFFSET_TABLE_+0x20>
4003ae: 68 01 00 00 00 pushq $0x1
4003b3: e9 d0 ff ff ff jmpq 400388 <_init+0x18>
So it's making a call into a "global offset table", which I would assume has all the syscall vectors. Like the other post said, see the kernel source (or standard library sources?) for details on that.

I don't think you want to do this. System call handling is complex (see http://www.ibm.com/developerworks/linux/library/l-system-calls/). Since you have tagged this question with "linux", you can just download the source from kernel.org (which will be far more understandable and informative than the assembly code).

For understanding linux system call, browse through the code.
Important files are:
/include/linux/syscalls.h (all the supported system calls in linux)
/arch/arm/kernel/entry-common.S (implementation of system call at register level)
/arch/arm/kernel/calls.S (system call numbers)
/arch/arm/include/asm/unistd.h (address of system call)
Note: system call table can be addressed only from system.map only.

Related

How to use bluetoothctl to report repeated proximity beacons in real time using MQTT

This is a great solution as far as it goes:
How to use bluetoothctl like hcitool lescan to report repeated proximity beacons
I want to take it one step further though: instead of printing the beacon detections to the terminal, I want to pipe each detected beacon's MAC address to a command that publishes it to a Mosquitto broker. This would be useful for adding the beacons to HomeAssistant, for example, for presence detection of a key fob attached to a person's house keys. I managed to get this idea to work by modifying the last two lines of the script above but it only publishes the first detection ... then no more. I guess somehow the scan is being turned off or aborted by trying to run the mosquitto_pub command. (something to do with interrupting the thread or subshells????)
Here are the last lines of the script with the MAC addresses of my TWO TEST BEACONS obfuscated.
You can see the full script that I modified at the link above.
) | sed --unbuffered --quiet --expression 's/^.*Device //p' \
| grep --line-buffered -E 'FF:FF::::|FF:GG::::' \
| stdbuf -oL cut -c 1-17 \
| { read topic; mosquitto_pub -d -u username -P password -m ON -t monitor/$topic; }
Note:
| stdbuf -oL cut -c 1-17 \ trims the output down to just the MAC address - e.g. FF:GG::::
The last line publishes the ON command to an unique state topic ending in the beacon's MAC address e.g. 'monitor/FF:GG::::'.
If I remove that last line the detections are added as they occur to the terminal console in an ever growing list as time goes by. But once I add the last line it only works once, then goes dead.
How can the script be made to respond to each detection, not just the first one?
And why exactly does it only respond to the first detection then hang?
The command line tools of BlueZ are not designed for this purpose, so it makes them very difficult to pipe scan results reliably. In my experience, processes die or hang, and you end up with broken pipes.
The C APIs of BlueZ are much more stable. I wrote a simple command line program in C that you could use instead of bluetoothctl for this purpose:
https://gist.github.com/davidgyoung/0a18028b4338ff6cb201fba274502662
That program must be compiled with cc scanner.c -lbluetooth -o scanner, after which you can start the scanner with just scanner. The output of the program will be something like this:
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
71:5C:23:9D:BC:7F -68 02 01 1A 02 0A 0C 0B FF 4C 00 10 06 03 1A 3B D4 B2 EB
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
4A:53:7F:64:71:EC -91 03 03 9F FE 17 16 9F FE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
69:0D:FF:7B:75:65 -73 02 01 1A 02 0A 0C 0A FF 4C 00 10 05 03 1C 27 BB 63
61:39:71:E9:1D:C9 -93 02 01 1A 02 0A 18 0A FF 4C 00 10 05 01 18 3B 24 12
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
Each line above shows the MAC address of the detected bluetooth device, followed by the signal strength RSSI, then the hex bytes of the advertisement.
I use this program to pipe into other shell scripts, and have found it to be reliable over many days. Feel free to use it if helpful.

Getting the hexdump of a given function

I want to get the hexdump of a given function. Until now objdump -d a.out --start-address=0x400630 and --stop-address=0x400679 is the best solution what I have found, however I do not know how to extract only the opcodes from the output.
For example from this:
4003f0: 48 83 ec 08 sub $0x8,%rsp
4003f4: e8 73 00 00 00 callq 40046c
...
I need only this:
48 83 ec 08
e8 73 00 00 00
You could use gdb on your program and x/i will print out a range of machine instructions.
May also try to pipe in cut:
objdump -d a.out --start-address=0x400630 and --stop-address=0x400679 | cut -b 14-30
you probably need to adapt your cut range for your output.

How to check which symbols on my shared library have non-position independent code (PIC)?

I'm trying to build a .deb package with debuild -i -us -uc -b and in the end I see:
Now running lintian...
warning: the authors of lintian do not recommend running it with root privileges!
W: libluajit-5.1-2: hardening-no-relro usr/lib/powerpc64le-linux-gnu/libluajit-5.1.so.2.1.0
E: libluajit-5.1-2: shlib-with-non-pic-code usr/lib/powerpc64le-linux-gnu/libluajit-5.1.so.2.1.0
W: luajit: hardening-no-relro usr/bin/luajit-2.1.0-alpha
W: luajit: binary-without-manpage usr/bin/luajit-2.1.0-alpha
Finished running lintian.
I have a hunch that I failed to define a "PIC code setup", which must be at the beginning of each external function:
The following code might appear in a PIC code setup sequence to compute
the distance from a function entry point to the TOC base:
addis 2,12,.TOC.-func#ha
addi 2,2,.TOC.-func#l
as specified by the ABI, page 99.
However I couldn't find the symbols which were non-PIC. Or maybe some relevant file that was not compiled with -fPIC?
Info:
system architecture: ppc64le
compiling .so library with: gcc -shared -fPIC
To find which symbols made your elf non-PIC/PIE (Position Independent Code/Executable), use scanelf from pax-utils package (on ubuntu, install it with sudo apt-get install pax-utils):
$ scanelf -qT /usr/local/lib/libluajit-5.1.so.2.1.0 | head -n 3
libluajit-5.1.so.2.1.0: buf_grow [0x7694] in (optimized out: previous lj_BC_MODVN) [0x7600]
libluajit-5.1.so.2.1.0: buf_grow [0x769C] in (optimized out: previous lj_BC_MODVN) [0x7600]
libluajit-5.1.so.2.1.0: buf_grow [0x76A0] in (optimized out: previous lj_BC_MODVN) [0x7600]
$ objdump -Sa /usr/local/lib/libluajit-5.1.so.2.1.0 | grep -A5 \ 7694:
7694: 00 00 80 39 li r12,0
7698: c6 07 8c 79 rldicr r12,r12,32,31
769c: 00 00 8c 65 oris r12,r12,0
76a0: 00 00 8c 61 ori r12,r12,0
76a4: a6 03 89 7d mtctr r12
76a8: 21 04 80 4e bctrl
On my case an absolute address was meant to be load on r12, but that's not possible for a dynamic library, so the linker used 0 for that parameter (I had to use #GOT operator, but that's the particular solution to my case).
On the luajit program, it's possible to define the address on linking time and it looks like this:
1003d0d4: 00 00 80 39 li r12,0
1003d0d8: c6 07 8c 79 rldicr r12,r12,32,31
1003d0dc: 07 10 8c 65 oris r12,r12,4103
1003d0e0: 30 ca 8c 61 ori r12,r12,51760
1003d0e4: a6 03 89 7d mtctr r12
Quite different right?
a much detailed explanation can be found on this wonderful Gentoo wiki page.
The failing lintian check is this:
# Now that we're sure this is really a shared library, report on
# non-PIC problems.
if ($objdump->{$cur_file}->{TEXTREL}) {
tag 'shlib-with-non-pic-code', $cur_file;
}
So you can probably find the offending file by looking for a .o that contains a TEXTREL dynamic section (which is making its way into your final link).
To do this, you can use readelf --dyanamic, in something like the following:
find . -name '*.o' |
while read obj
do
if readelf --dynamic "$obj" | grep -q TEXTREL
then
echo "$obj contains a TEXTREL section"
fi
done

Using hcitool to set ad packets

There is a well known blog post going around on how to set a usb bluetooth 4 dongle to be an iBeacon. It boils down to this magical command:
sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00
The issue with this example is that it is so opaque it's hard to use it in any more general format. I've been able to break it apart a bit:
sudo hcitool -i hci0 cmd
sends an hci command to the hci0 device
0x08 0x0008
is just magic to set the ad package, other stackoverflow commands have said "just use it, don't ask
1e
is the length of the ENTIRE following data packet in bytes
02 01 1a 1a
Are flags to set up the ad packet (details on request)
ff 4c 00 ...
is the 'company specific data' that encodes the iBeacon info
What I've tried to do is replace the "FF ..." bytes with the opcodes for setting the NAME parameter "04 09 41 42 43" (which should set it to ABC) but that doesn't work.
I'm surprised the hcitool doesn't give us some examples on how to set the ad packet as this would be very useful in setting all sorts of other params (like TEMP or POWER). Has anyone else had any experience in using hcitool to set things like NAME?
Late reply, but somebody might find this useful. I found it as I was looking around for solutions myself when using hcitool.
If you use hcitool cmd --help it will tell you something like this cmd <ogf> <ocf> .... It helps to look at the Bluetooth Core Specification to find out what 0x08 and 0x0008 would be for OGF and OCF. Specifically Vol. 2, Part E, 7.8
For the LE Controller Commands, the OGF code is defined as 0x08
and for the OCF of 0x0008
Advertising_Data_Length, Advertising_Data
So basically, with 0x08 0x0008 you say you are setting (in the LE Controller) the length of the data that is sent. As for the name, since the length of the BLE advertisement packet is 31 bytes (1E), you need to send the whole 31 bytes. So if you only have ABC as the name, setting 04 09 41 42 43 is correct, but that's only five bytes. For 31 you need to add 00 26 times. Just be careful you don't add too much or too little.
Also, I wasn't under the impression that BLE ad. packets are of fixed 31 byte size, but they are at least for hcitool. It doesn't work when you specifically set the outgoing size to something smaller than 1E.
No. None of this answers is correct and clean.
1) BLE have a separate command set. "LE Set Advertising Data" command must be used (see 7.8.7 vol 2 part E).
2) LE Set Advertising Data is much complex than what explained above. There are at least 2 1-octet length fields, packet must be 32 bytes length, zero padded, but the first length byte must not be 0x1e (31) but the length of the significant used part, containing one or more headers. Each header still contains a length, one AS Type byte (0x09 for set local name) and the name.
SET LE LOCAL NAME:
hciconfig hci0 down
hciconfig hci0 up
hcitool -i hci0 cmd 0x08 0x0008 0c 0b 09 6c 69 6e 6b 6d 6f 74 69 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
hciconfig hci0 leadv 0
0x0c : length of the following group of headers
0x0b : length of this header
0x09 : AD Type for complete name
rest 0x0a length is the name
Check out this answer to a similar question. It basically describes how you can download the giant Bluetooth Core Spec document, and read through all the commands that it offers you. You can use the hcitool command to execute any of these commands if you can just figure out the right format (and figure out what the commands actually do!)
Major caveat: I have not tried setting the name myself, but glancing at the spec, it looks like this is described on page 482 of the spec in section "7.3.11 Write Local Name Command". According to this the command consists of:
OCF: 0x0013
Name (up to 248 bytes)
So I would try a command like this:
hcitool -i hci0 cmd 0x08 0x0013 41 42 43
One other tip: When you issue commands like this, try running hcidump & so the command executes in the background. Then, you can enter experimental hcitool commands (or even hciconfig commands) and see annotated details about what (human readable) commands executed and what errors occurred, if any.
Using the above tip, you can also try executing hciconfig name abc to set the local name using that command line tool, while you are executing a hcidump & in the background. This should show you the proper hcitool command values to use.
It would appear you need to use two commands rather than one. The iBeacon data is contained in the "LE Set Advertising Data" data and has been mentioned elsewhere in this post. To see a BLE friendly name you can use an additional command "LE Set Scan Response Data", this requires the receiver to scan your device (rather than passively read the advertising packet). So you can combine Angelo's example with this one to set the device as an iBeacon and set the "friendly name" which is the Scan Response data
sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00
sudo hcitool -i hci0 cmd 0x08 0x0009 0c 0b 09 6c 69 6e 6b 6d 6f 74 69 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
This worked for me using an Ubuntu box with a BLE dongle and then scanning for the beacon using this android BLE scanning app

What does "echo 1 > rom" for PCI devices do, and how can I do it programatically?

I am trying to write a program to dump option/expansion ROMs on linux. I already have the necessary PCI port IO to get an expansion ROM's base address out of the PCI configuration data at offset 0x30 and make it enabled, but when I try to access the base in memory I get a segfault. So I am trying to understand what is happening when you do the "echo 1 > rom" from a linux command line, since after that the rom seems plenty accessible (see here for a little more context: http://etherboot.org/wiki/romdumping)
E.g. let's say I do the following:
lspci
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
cd /sys/bus/pci/devices/0000:01:00.0
lspci -x -v -s 01:00.0
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
Subsystem: ATI Technologies Inc Device 0402
Flags: bus master, fast devsel, latency 0, IRQ 27
Memory at d0000000 (32-bit, prefetchable) [size=128M]
I/O ports at dc00 [size=256]
Memory at dfde0000 (32-bit, non-prefetchable) [size=64K]
Expansion ROM at dfe00000 [disabled] [size=128K]
Capabilities: [50] Power Management version 2
Capabilities: [58] Express Endpoint, MSI 00
Capabilities: [80] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable+
Capabilities: [100] Advanced Error Reporting <?>
Kernel driver in use: radeon
Kernel modules: radeonfb, radeon
00: 02 10 60 5b 07 04 10 00 00 00 00 03 10 00 80 00
10: 08 00 00 d0 01 dc 00 00 00 00 de df 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 02 10 02 04
30: 00 00 e0 df 50 00 00 00 00 00 00 00 0b 01 00 00
Note the line that says "Expansion ROM at dfe00000 [disabled] [size=128K]"
Now per the PCI spec I can see that the bottom bit should be set to 1 to enable the expansion ROM, so I did a read and write back of 0xdfe00001, and then I get
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 5B60 [Radeon X300 (PCIE)]
Subsystem: ATI Technologies Inc Device 0402
Flags: bus master, fast devsel, latency 0, IRQ 27
Memory at d0000000 (32-bit, prefetchable) [size=128M]
I/O ports at dc00 [size=256]
Memory at dfde0000 (32-bit, non-prefetchable) [size=64K]
Expansion ROM at dfe00000 [size=128K]
Capabilities: [50] Power Management version 2
Capabilities: [58] Express Endpoint, MSI 00
Capabilities: [80] Message Signalled Interrupts: Mask- 64bit+ Queue=0/0 Enable+
Capabilities: [100] Advanced Error Reporting <?>
Kernel driver in use: radeon
Kernel modules: radeonfb, radeon
00: 02 10 60 5b 07 04 10 00 00 00 00 03 10 00 80 00
10: 08 00 00 d0 01 dc 00 00 00 00 de df 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 02 10 02 04
30: 01 00 e0 df 50 00 00 00 00 00 00 00 0b 01 00 00
(note the 0x01 at offset 0x30 and the line now saying "Expansion ROM at dfe00000 [size=128K]").
But I can't access 0xdfe00000. Meanwhile, when O do the "echo 1 > rom" in the command line, it does NOT change the line to remove the "disabled", and really it doesn't make any change at all to the output of lspci. So what is the "echo 1 > rom" doing that I'm not, which makes it subsequently possible to do the "dd if=rom of=/tmp/rom"?
Much appreciated
I've tried to get the exROM contents from an NVidia VGA board (NVS310) - from the Linux command line :-)
This is what I did, approximately:
From lspci -vvn, I found out that my board is at 0000:02:00.0 and its exROM is at 0xf7000000 size 512 kB (and its address decoder is disabled in the exROM BAR = via bit 0 in PCI config space reg #c0 == offset 0x30).
I then used setpci to toggle that "exROM BAR enable bit" in the PCI config space. Notice the notation value:mask in the "write" form of setpci:
setpci --dumpregs
setpci -s 0000:02:00.0 ROM_ADDRESS
setpci -s 0000:02:00.0 ROM_ADDRESS=00000001:00000001
setpci -s 0000:02:00.0 ROM_ADDRESS
lspci -vvn -s 0000:02:00.0
dd if=/dev/mem of=vgabios.bin bs=64k skip=63232 count=8
Which resulted in some semi-plausible looking binary data in a file 512 kB long.
Access via /sys/bus/pci/devices/0000:02:00.0/rom did not work, even after I wrote a "1" into that pseudo-file.
rom is a special file usually read-protected unless '1' is written to it, from sysfs-pci.txt:
The 'rom' file is special in that it provides read-only access to the device's
ROM file, if available. It's disabled by default, however, so applications
should write the string "1" to the file to enable it before attempting a read
call, and disable it following the access by writing "0" to the file. Note
that the device must be enabled for a rom read to return data successfully.
In the event a driver is not bound to the device, it can be enabled using the
'enable' file, documented above.
So it looks like 'echo 1 > rom' really only enables reading the rom through sysfs.
Maybe you can't access the rom through its bar because it's not mapped to dfe00000 by default? Not sure, worth checking though.
sudo echo 1 >rom for me (a zsh user) outputs permission denied: rom and the same seems to be the case when using bash, when using su and then typing echo 1 >rom works. If you are scripting you may need to thus do sudo su -c 'echo 1 >rom' or pkexec --keep-cwd su -c 'echo 1 >rom'. Perhaps it can also depend on your system (security) configuration. All I can say in that regard is that I use arch linux, without mitigations and linux-zen 5.19

Resources