How do I detect programmatically in which ring (-1, 0, 1, 2, 3) I am running? - virtual-machine

How do I detect programmatically in which ring (-1, 0, 1, 2, 3) I am running?

The easiest way is, to just run the (x86) command and catch the corresponding error.
E.g. (SEH, Windows, kernel mode)
bool ring_lower_0 = false;
__try
{
__asm { <cmd> };
ring_lower_0 = true;
}
__except( GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION )
{
ring_lower_0 = false;
}
Notes:
cmd, is an assembler command. See the Intel Architecture Reference Manuals for a list of commands and their respective Ring levels.
Linux has a slightly different concept.
But remember that VMs residing on a lower level may mask the result by emulating the call.
(NB: The Job of the VM is to translate the invalid instruction into an meaningful call)
If you really want to check if your a virtualized and want to stop execution because of this, you should read what has been written about 'Red pill'.

Unless you're a device driver, you'll always be running in Ring 3 (for systems that have "rings", per se).

Normally i would write that you should read about "protected mode programming". There is an article about how to intertact with ring 0 using windows XP SP2. Note that it will change for others windows versions and for sure others operational systems.
http://www.codeproject.com/KB/threads/MinimalisticRingZero.aspx
If you just want to detect if you are running inside of a virtual machine, to avoid that people debug your application, for example, you can check here:
http://www.codeproject.com/KB/system/VmDetect.aspx

The ring are the lower two bits of the code segment selector (CS) register in the 64-bit x86 architecture.
You can extract it like this: (test it online)
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint64_t rcs = 0;
int ring;
asm ("mov %%cs, %0" : "=r" (rcs));
ring = (int) (rcs & 3);
printf("Hello, world. This program is running on ring %d!\n", ring);
return 0;
}
The problem with that code is that it will always return 3, because your code will always run on ring 3. To see that changing you need to create a Linux Kernel Module or Windows Device Driver.
I have a github repo where i was playing around with this in Ubuntu 18.
In the demo 1 I have the exact same code as above. You can run it:
cd demo-1
. c-build.sh
In the demo-2 I have a Linux Kernel module that will execute the same code, but inside the kernel in ring 1:
link to code:
...
#define EXAMPLE_MSG "Hello, World. This is executed in ring: _ \n"
...
uint64_t rcs = 0;
asm ("mov %%cs, %0" : "=r" (rcs));
msg_buffer[MSG_BUFFER_LEN - 3] = (int) (rcs & 3) + '0';
You cannot do printf to the console from the kernel driver. Instead you need to open the device as a file and read from it:
cat /dev/lkm_example
I would recommend you to follow the readme step by step, so you can see it running :)

Related

Read running processes' virtual memory from mm_struct in linux

I'm trying to write a kernel module that uses the proc file system to read the total memory of each running process. This is for an assignment and it is suggested that use the information of the "mm_struct" which is inside " "task_struct". I should compare the output of content of the proc file with what I obtain from running "ps -ef". I'm using the seq_file API to read from the proc file. My current read function looks like this:
static int proc_show(struct seq_file *m, void *v){
struct task_struct *task;
/*struct mm_struct *mm; Commented this since it's inside task_struct
*struct vm_area_struct *mmap; Commented this since it's inside task_struct */
unsigned long size;
for_each_process(task){
seq_printf(m,"Task = %s PID = %d\n",task->comm,task->pid);
down_read(&task->mm->mmap_sem);
if(task->mm){
size = (task->mm->mmap->vm_end - task->mm->mmap->vm_start );
seq_printf(m," VIRT = %lu\n",size);
}else{
seq_printf(m," VIRT = 0\n");
}
up_read(&task->mm->mmap_sem);
}
return 0;
}
The message "Killed" is promted as soon I try "~# cat proc/my_proc_file". So far what I think I now is that vm_area_struct is inside of mm_struct which is inside task_struct, all of them defined in the include /linux/sched.h.
A similar question, which is the one I partially based this code on, was posted by #confusedkid (see the post Linux Kernel programming: trying to get vm_area_struct->vm_start crashes kernel). However the replies contradict each other and no one actually explains the reasoning behind the code.
Could anyone please point out what the problem might be or suggest any documentation that explains how to access these structure correctly?

How to demonstrate a memory misalignment error in C on a macbook pro (Intel 64 bit processor)

In an attempt to understand C memory alignment or whatever the term is (data structure alignment?), i'm trying to write code that results in a alignment error. The original reason that brought me to learning about this is that i'm writing data parsing code that reads binary data received over the network. The data contains some uint32s, uint64s, floats, and doubles, and i'd like to make sure they are never corrupted due to errors in my parsing code.
An unsuccessful attempt at causing some problem due to misalignment:
uint32_t integer = 1027;
uint8_t * pointer = (uint8_t *)&integer;
uint8_t * bytes = malloc(5);
bytes[0] = 23; // extra byte to misalign uint32_t data
bytes[1] = pointer[0];
bytes[2] = pointer[1];
bytes[3] = pointer[2];
bytes[4] = pointer[3];
uint32_t integer2 = *(uint32_t *)(bytes + 1);
printf("integer: %u\ninteger2: %u\n", integer, integer2);
On my machine both integers print out the same. (macbook pro with Intel 64 bit processor, not sure what exactly determines alignment behaviour, is it the architecture? or exact CPU model? or compiler maybe? i use Xcode so clang)
I guess my processor/machine/setup supports unaligned reads so it takes the above code without any problems.
What would a case where parsing of say an uint32_t would fail because of code not taking alignment in account? Is there a way to make it fail on a modern Intel 64 bit system? Or am i safe from alignment errors when using simple datatypes like integers and floats (no structs)?
Edit: If anyone's reading this later, i found a similar question with interesting info: Mis-aligned pointers on x86
Normally, the x86 architecture doesn't have alignment requirements [except for some SIMD instructions like movdqa).
However, since you're trying to write code to cause such an exception ...
There is an alignment check exception bit that can be set into the x86 flags register. If you turn in on, an unaligned access will generate an exception which will show up [under linux at least] as a bus error (i.e. SIGBUS)
See my answer here: any way to stop unaligned access from c++ standard library on x86_64? for details and some sample programs to generate an exception.

Getting GPS to Work on SIM5320A 3G/GPS Module

I have a Adafruit FONA 3G/GPS module (American Version). I have gotten the cellular functionality to work but I am struggling with GPS. I have tried both passive and active antennas.
This is a list of AT commands that are available to the SIM5320A module (pdf). The Adafruit example code uses AT commands that don't run on this SIM module. I send the following sequence:
AT+CGPS=1,1
AT+CGPSINFO
and I am receiving:
+CGPSINFO: ,,,,,,,,
AmpI/AmpQ: 4xx/4xx
What exactly is going wrong? I am connected but am not getting any data out. Also, I understand the mathematical significance of AmpI/AmpQ but what does that mean in terms of connection to GPS network?
First, if you're using the FONATest example from Adafruit, you need to look around line 48. Comment out the line that declares a variable of type Adafruit_FONA and uncomment the line that declares a variable of type Adafruit_FONA_3G.
Also, if you haven't run the FONA_3G setbaud program to set the baud rate to something other than 115,200, you need to run it. (This isn't made very clear by Adafruit, and I thought my board was bad before I found that information.)
Second, unless you bridge the pads labeled bias on the board, you will have to use a passive GPS antenna. The SIMCOM module's GPS is pretty sensitive though. I had a uFL-to-SMA adapter plugged into the board, and stuck a 5-inch jumper wire into the SMA's center pin. The GPS acquired a position within a minute!
I tried the following command: AT+CGPS=1 and then used AT+CGPS? to query the GPS status. It reported +CGPS: 1,1 back to me.
The first few attempts at sending AT+CGPSINFO gave me the same info that you got, i.e. no position.
However, after a few minutes with a wire (or passive antenna), AT+CGPSINFO started returning valid time and position information.
Hope this helps.
UPDATE:
You've asked for code, and I'm happy to oblige. This code is designed to just be a terminal-like relay for serial data between the Arduino (using Tools -> Serial Monitor) and the Fona. So the commands I described above, I just entered by hand. Still, some folks may find it useful.
#include <Adafruit_FONA.h>
#include <SoftwareSerial.h>
#define RX_FROM_FONA 2
#define TX_TO_FONA 3
#define FONA_RST 4
#define FONA_PWR_KEY 5
#define FONA_PWR_STATUS 7
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
SoftwareSerial fonaSerial = SoftwareSerial(TX_TO_FONA, RX_FROM_FONA);
void setup() {
pinMode(FONA_RST, OUTPUT);
pinMode(FONA_PWR_KEY, OUTPUT);
pinMode(FONA_PWR_STATUS, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(FONA_RST, HIGH);
digitalWrite(FONA_PWR_KEY, HIGH);
resetFona();
Serial.begin(115200);
fonaSerial.begin(4800);
}
void resetFona() {
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_RST, LOW);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_RST, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_PWR_KEY, LOW);
delay(5000);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_PWR_KEY, HIGH);
delay(100);
}
char buffer[255];
int crIndex = 0;
int bufferIndex = 0;
int foundCR = 0;
void loop() {
if (Serial.available()) {
buffer[bufferIndex++] = Serial.read();
if (buffer[bufferIndex - 1] == 13) {
crIndex = bufferIndex - 1;
foundCR = 1;
}
}
if (bufferIndex > 255) { bufferIndex = 0; }
while (fonaSerial.available()) { Serial.write(fonaSerial.read()); }
if (foundCR > 0) {
for (int i = 0; i <= crIndex; i++) {
fonaSerial.write(buffer[i]);
}
foundCR = 0;
bufferIndex = 0;
crIndex = 0;
}
}
I don't think this is a software problem, I think you have a hardware problem.
I had this same problem. The sensitivity of the SIM5320A is pretty good, but Adafruit hasn't really followed their design guide in implementing the carrier board, and this hurts its sensitivity.
For example, you can read the application notes for the board here. Check out the PDFs on "SMT Module Design" and "Hardware Design."
First thing you'll notice is SIMCOM recommends a LC tuning network to tune your particular antenna to 50-ohm impedance.
Here is the SIMCOM recommended diagram:
And here is the Adafruit design, with no tuning network anywhere to be found:
Now, if you're going to be using this in your own PCB later, you of course are free to make improvements here yourself.
To test your design, you're going to want to know more about what the module is saying, otherwise you're flying blind. You can read the GPS NMEA sequences and decipher them, but there's a lot to it. Another way is to use the GPS demo tool that SIMCOM support offers. To download this, go to:
ftp://simcom.exavault.com/SIM5320A/GPS tool
username=myd
psd=simcommyd
It will show you how many satellites you're connected to, what signal strength they have, etc. You are going to need at least 3 satellites for a lock (technically you should have 4, but some modules will toss out an impossible triangulation solution with just 3, not sure which the SIM5320A has). You want each satellite to have strengths in the 30+ range.
Here is my Before screenshot, you can see I only had one satellite and hence no lock. This was after giving half an hour after cold start to download the almanac and ephemeris tables (will take about 15min on average from cold start). Satellite 21 (with signal of also 21 strength, coincidentally).
What I did to fix my signal gain was add an LNA (Low Noise Amplifier) in series with my passive antenna. I used the BGA524N6BOARDTOBO1 breakout board, which you can get at DigiKey/Mouser/others, and adds 19dB of gain, and an incredibly-low 0.55dB noise figure.
After hooking up my antenna, and waiting some time, I got a lock!
Hope this helps you and others to use this otherwise great module.

Glowing an LED using GPIO in craneboard

I'd like to use GPIO to turn on an LED in a craneboard (ARM processor). I'm very new to embedded programming. But, I'm quite good at C. I referred in some websites and learnt about GPIO related commands. I wrote a code, but I'm not quite sure in how to integrate it to the u-boot coding of the craneboard. I don't know where to start. Kindly guide me.
#define LED1 (1 << 6)
int getPinState(int pinNumber);
int main(void)
{
GPIO0_IODIR |= LED1;
GPIO0_IOSET |= LED1;
while (1)
{
GPIO0_IOCLR |= LED1;
}
}
int getPinState(int pinNumber)
{
int pinBlockState = GPIO0_IOPIN;
int pinState = (pinBlockState & (1 << pinNumber)) ? 1 : 0;
return pinState;
}
First of all, learn common bit (also pin in your case) manipulation expressions that you will use A LOT in embedded programming:
/* Set bit to 1 */
GPIO0_IODIR |= LED1; //output
/* Clear bit (set to 0) */
GPIO0_IOSET &= ~LED1; //low
/* Toggle bit */
GPIO0_IOSET ^= LED1;
Your while() loop actually does nothing, except for the first iteration, because the same logical OR operations do no change bit state (see logical table of this op). Also you should add delay, because if pin toggles too fast, LED might look like off all the time. Simple solution would look like:
while(1)
{
GPIO0_IOSET ^= LED1;
sleep(1); //or replace with any other available delay command
}
I do not have source files of U-Boot for Craneboard, so cannot tell you the exact place where to put your code, but basically there are several options: 1) add it in main(), where U-Boot start, thus hanging it (but you still have LED blinking!). 2) implement separate command to switch LED on/off (see command.c and cmd_ prefixed files for examples) 3) Integrate it in serial loop, so pin could be switched while waiting user input 4) build it as an application over U-Boot.
Get used to a lot of reading and documentation, TRM is your friend here (sometimes the only one). Also there are some great guides for embedded starters, just google around. Few to mention:
http://www.microbuilder.eu/Tutorials/LPC2148/GPIO.aspx (basics with examples)
http://beagleboard.org/ (great resource for BeagleBoard, but much applies to CraneBoard as they share the same SoC, includes great community).
http://free-electrons.com/ (more towards embedded Linux and other advanced topics, but some basics can also be found)
http://processors.wiki.ti.com/index.php/CraneBoard (official CraneBoard wiki, probably know this, but just in case)
P.S. Good luck in and don't give up!
If you want to do it in u-boot (and not in Linux), then you have to write an application for u-boot.
$5.12 of u-boot manual explains how to do it.
The source of u-boot provides some examples that you can use.
I'd like to add my answer. The coding that I have done previously was a generalized one. In craneboard, there are certain functions, that does the operation. So, I rewrote it accordingly. I included the file cmd_toggle.c in 'common' directory in the u-boot directory. And added it to the Makefile. The following code will make the LED to blink.
int glow_led(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int ret,i=0,num=0,ctr=0;
int lpin;
lpin=(int)strtoul(argv[1]);
ret=set_mmc_mux();
if(ret<0)
printf("\n\nLED failed to glow!\n\n");
else{
if(!omap_request_gpio(lpin))
{
omap_set_gpio_direction(lpin,0);
for(i=1;i<21;i++)
{
ctr=0;
if((i%2)==0)
{
num=num-1;
omap_set_gpio_dataout(lpin,num);
}
else
{
num=num+1;
omap_set_gpio_dataout(lpin,num);
}
udelay(3000000);
}
}
}
return 0;
}
U_BOOT_CMD(toggle,2,1,glow_led,"Glow an LED","pin_number");
I could've made this a little simpler by just using a while loop to repeatedly set it as 1 and 0.
This can be executed from the u-boot console as toggle 142, as I have connected the LED to the pin 142.
P.S
Thanks for all your guidance. A special thanks to KBart

HDD serial number flipped every 2 bytes in Windows XP, Vista and 7 but not in Windows 8

I need to get HDD serial number to use it as a key for licensing a software.
I used diskid32 code in this url: http://www.winsim.com/diskid32/diskid32.html
It used the DeviceIoControl Win32 API with the IO control code of IOCTL_STORAGE_QUERY_PROPERTY.
It worked. However, when I double check with the actual serial number printed on the HDD itself, I found that every 2 bytes of the number was flipped.
A simple solution could be to simply flip the bytes back. It worked in Windows XP, Vista and 7 but in windows 8 not need to be flipped!
I wish to know the exact reason why the bytes were flipped in Windows XP, Vista and 7, and why not flipped in Windows 8. What about next Windows?
Part of code with minor changes:
int drive = 0;
HANDLE hPhysicalDriveIOCTL = 0;
char driveName [256];
sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT, Windows 2000, Windows XP - admin rights not required
hPhysicalDriveIOCTL = CreateFile (driveName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
_STORAGE_PROPERTY_QUERY query;
DWORD cbBytesReturned = 0;
char buffer [10000];
memset ((void *) & query, 0, sizeof (query));
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
memset (buffer, 0, sizeof (buffer));
if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
& query,
sizeof (query),
& buffer,
sizeof (buffer),
& cbBytesReturned, NULL) )
{
_STORAGE_DEVICE_DESCRIPTOR * descrip = (_STORAGE_DEVICE_DESCRIPTOR *) & buffer;
char serialNumber [1000];
char modelNumber [1000];
char vendorId [1000];
char productRevision [1000];
flipAndCodeBytes (buffer,
descrip -> SerialNumberOffset,
1, serialNumber );
...
}
I use the same approach (and same code) in my software licensing. Yes, Windows 8 for some reason is returning flipped values for this method, I can't say why (so I can't answer your question).
My solution is the one that you pointed out: Flip the values again.
So, after calling the "flipAndCodeBytes", you could test if is a Windows 8 OS, and flip the values.
In my case, it's working now (I got the same values for Windows XP/Vista/7 and Windows 8).
Good luck!
Just turn off the flip using the "flip" flag of the flibAndCodeBytes function when windows 8 or greater.
bool shoulFlipBytes = true;
if(IsWin8OrLater()) shouldFlipBytes = false;
flipAndCodeBytes(buffer,
descrip->SerialNumberOffset,
shouldFlipBytes,
serialNumber);
You can use this to check for windows version:
#include <windows.h>
bool IsWin8OrLater() {
DWORD version = GetVersion();
DWORD major = (DWORD) (LOBYTE(LOWORD(version)));
DWORD minor = (DWORD) (HIBYTE(LOWORD(version)));
return (major > 6) || ((major == 6) && (minor >= 2));
}
According to http://msdn.microsoft.com/en-us/library/ms724832%28VS.85%29.aspx
(Thanks to ChrisV Determine if O/S is Windows 7)
Basically you're relying on data that's not strictly reliable to begin with. Drives may change over the lifetime of a computer; all the while getting exactly the right serial number isn't even important to your product.
One easy hack I can think of is to normalize the serial number, e.g. by sorting the digits; this will make more drives look alike, but I doubt it will become an issue.
Another way of looking at the problem is that the application should provision for serial number changes; the user could be informed about the licensing issue (for whatever reasons) and asked to contact the support department with a generated code (not necessarily the serial number itself). Given this code, support can then create a new license for the customer.
Seem you have to check for windows version through API and add if() branch to your code if version is high enough
My devs found other problem with this method - that kind of IOCtl code relies on program is being run with administrator rights on Win7\Win8+. In cause of our software, it's service that is run with system rights and clients software that is strictly run with user rights
For licensing-checking purposes, you really don't care. All you need to know is that some configurations result in flipping, some don't, and it can change during the lifetime of a license.
So accept both variants:
string serial = get_serial();
if (license_check(serial)) {
licensed = true;
return;
}
serial = swap_bytes(serial);
if (license_check(serial)) {
licensed = true;
return;
}
(I see Raymond suggested this in a comment)
No fragile OS check, no worries about whether it failed to flip right when the user applied for the license. Just happy users.