I have to validate a vulnerability on one of our 64-bit systems which is running glibc-2.9 .
http://scarybeastsecurity.blogspot.in/2011/02/i-got-accidental-code-execution-via.html
The above link gives a script which when passed a magic number apparently leads to arbitrary code execution. But when I tried it on my system, nothing seems to be happening.
Am I doing something wrong? Does the system crash if the vulnerability exists? How do I detect if it's accidental code execution?
If you're running on a 64-bit machine then the original circumstances of the bug don't apply. As you can see in Chris' blog, he's using a 32-bit Ubuntu 9.04 system. The exploit relies on causing the stack pointer to wrap about the 32-bit address space, leading to stack corruption.
I gave it a quick try on a 64-bit system with glibc 2.5, but saw malloc() failures instead of crashes.
$ ./a.out 3000000000
a.out: malloc() failed.
You asked how to identify accidental code execution; with the toy program here, which doesn't carry an exploit / payload, we'd expect to see either a SIGSEGV, SIGILL, or SIGBUS as the CPU tried to "execute" junk parts of the stack, showing up as the respective error message from the shell.
If you were to run into the problem on a 64-bit machine, you'd have to mimic the original code but provide a number that wraps the stack on a 64-bit machine. The original number provided was:
1073741796
$ bc
z=1073741796
z+28
1073741824
(z+28)*4
4294967296
2^32
4294967296
quit
$
So, one way of describing the input number is (ULONG_MAX - 112) / 4.
The analogue number for a 64-bit machine is 4611686018427387876:
$ bc
x=2^64
x
18446744073709551616
y=x/4
y
4611686018427387904
y-28
4611686018427387876
quit
$
However, to stand a chance of this working, you'd have to modify the reported code to use strtroull() or something similar; atoi() is normally limited to 32-bit integers and would be no use on the 64-bit numbers above. The code also contains:
num_as = atoi(argv[1]);
if (num_as < 5) {
errx(1, "Need 5.");
}
p = malloc(num_as);
Where num_as is a size_t and p is a char *. So, you'd have to be able to malloc() a gargantuan amount of space (almost 4 EiB). Most people don't have enough virtual memory on their machines, even with disk space for backing, to do that. Now, maybe, just maybe, Linux would allow you to over-commit (and let the OOM Killer swoop in later), but the malloc() would more likely fail.
There were other features that were relevant and affect 32-bit systems in a way that it cannot affect 64-bit systems (yet).
If you're going to stand a chance of reproducing it on a 64-bit machine, you probably have to do a 32-bit compilation. Then, if the wind is behind you and you have appropriately old versions of the relevant software perhaps you can reproduce it.
Related
I'm using Peter Below's PBThreadedSplashForm to display a splash window during application startup.
This component worked great for 10 years, but, since updating my Delphi to 11.2, I get an AV on the CreateWindowEx call.
This happens on Win64 platform only, on problems on Win32.
Anyone who knows what can be the cause of this?
This is one of the many issues that have surfaced in 11.2 due to the new default ASLR settings in the compiler and linker.
After a very quick glance at the source code I see this:
SetWindowLong( wnd, GWL_WNDPROC, Integer( thread.FCallstub ));
thread.FCallstub is defined as Pointer.
Just as I thought.
You see, pointers are of native size, so in 32-bit applications, pointers are 32 bits wide, while in 64-bit applications, pointers are 64 bits wide.
It was very common in the 32-bit world that pointer values were temporarily saved in Integers. This worked because a 32-bit pointer fits in a 32-bit Integer.
But in a 64-bit application, this is an obvious bug, since a 64-bit pointer doesn't fit in a 32-bit Integer. It's like taking a phone number like 5362417812 and truncating it to 17812, hoping that it will still "work".
Of course, in general, this causes bugs such as AVs and memory corruption.
However, until recently, there was a rather high probability that a pointer in a 64-bit Delphi application by "chance" didn't use its 32 upper bits (so it was like maybe $0000000000A3BE41, and so truncating it to $00A3BE41 didn't have any effect). So it seemed to work most of the time, but only by accident.
Now, recent versions of the Delphi compiler and linker enables ASLR, making such accidents much less likely.
And this is a good thing: If you have a serious bug in your code, it is better if you discover it right away and not "randomly" at your customers.
So, to fix the issue, you need to go through the code and make sure you never store a pointer in a 32-bit Integer. Instead, use a native-sized NativeInt, Pointer, LPARAM, or whatever is semantically appropriate.
(Disabling ASLR will also make it work in "many" cases by accident again, but this is a very bad approach. Your software still has a very serious bug that may manifest itself at any time.)
In your code, there is also
Integer( Pchar( FStatusMessage ))
Integer( Pchar( msg ))
What is the command for finding the number of bit of an OS/390 or a z/OS?
Since there didn't seem to be a "real" answer on this thread, I thought I'd provide one just in case anyone needs the information...
The definitive source of whether you're running in 64-bit mode is the STORE FACILITY LIST (STFL, or STFLE) hardware instruction. It sets two different bits - one to indicate that the 64-bit zArchitecture facility is installed, and one to indicate that the 64-bit zArchitecture facility is active (it was once possible to run in 31-bit mode on 64-bit hardware, so this would give you the "installed, but not active" case).
The operating system generously issues STFL/STFLE during IPL, saving the response in the PSA (that's low memory, starting at location 0). This is handy, since STFL/STFLE are privileged instructions, but testing low storage doesn't require anything special. You can check the value at absolute address 0xc8 (decimal 200) for the 0x20 bit to tell that the system is active in 64-bit mode, otherwise it's 31-bit mode.
Although I doubt there are any pre-MVS/XA systems alive anymore (that is, 24-bit), for completeness you can also test CVTDCB.CVTMVSE bit - if this bit is not set, then you have a pre-MVS/XA 24-bit mode system. Finding this bit is simple - but left as an exercise for the reader... :)
If you're not able to write a program to test the above, then there are a variety of ways to display storage, such as TSO TEST or any mainframe debugger, as well as by looking at a dump, etc.
While I was not able to find commands to give this information, I think below is what you're looking for:
According to this: https://en.wikipedia.org/wiki/OS/390
z/OS is OS/390 with various extensions including support for 64-bit architecture.
So if you're on a zSeries processor with z/OS, you're on 64-bit.
According to this: https://en.wikipedia.org/wiki/IBM_ESA/390
OS/390 was installed on ESA/390 computers, which were 32-bit computers, but were 31-bit addressable.
For either z/OS or OS/390 I believe you can do a D IPLINFO and look for ARCHLEVEL. ARCHLEVEL 1 = 31 bit, ARCHLEVEL 2 = 64 bit. But it's been a very long time since I've been on an OS/390 system.
Is it possible to use sysenter in a 64 bits program on Linux ? Or is it impossible to adapt the use of sysenter with the SystemⅤ calling convention without getting other dynamic link libraries crashing (I know the 32 bits way won’t work but I just want to know if it’s possible to work around this like withint 0x80) ?
There is very few documentation around using sysenter in 32 bits, so I couldn’t found anything for 64 bits.
I know this not recommended but it’s the only opcode I can use to trigger a system call as part of bug bounty hunting exploit where the program need to exit using a special function that can be trigger only from normal execution.
It is possible to use them, but they use the 32-bit entry point of the kernel (check the code for more).
The actual location (and code) of this entry point depends on you kernel version.
For versions 4.2 and newer it is entry_SYSENTER_32.
For versions 4.1 and older it is ia32_sysenter_target.
Finally, SYSRET is not available at userspace (it can only be executed from ring 0). Check the Intel manual description of the instruction.
I am aware that an implementer has a choice of whether he wants to zero a malloc page or let OS give him a zeroed page (for more optimization purposes).
My question is simple - in Ubuntu 14.04 LTS which comes with linux kernel 3.16 and gcc 4.8.4, who will zero my pages? Is it in user land or kernel land?
It can depend on where the memory came from. The calloc code is userland, and will zero a memory page that gets re-used by a process. This happens when the memory is previously used and then freed, but not returned to the OS. However, if the page is newly allocated to the process, it will come already cleared to 0 by the OS (for security purposes), and so does not need to be cleared by calloc. This means calloc can potentially be faster than calling malloc followed by memset, since it can skip the memset if it knows it will already by zeroed.
That depends on the implementer of your standard library, not on the host system. It is not possible to give a specific answer for a particular OS, since it may be the build target of multiple compilers and their libraries - including on other systems, if you consider the possibility of cross-compiling (building on one type of system to target another).
Most implementations I've seen of calloc() use a call of malloc() followed by either a call of memset() or (with some implementations that target unix) a legacy function called bzero() - which is, itself, sometimes replaced by a macro call that expands to a call of memset() in a number of recent versions of libraries.
memset() is often hand-optimised. But, again, it is up to the implementer of the library.
Basically, what I wonder is how come an x86-64 OS can run a code compiled for x86 machine. I know when first x64 Systems has been introduced, this wasn't a feature of any of them. After that, they somehow managed to do this.
Note that I know that x86 assembly language is a subset of x86-64 assembly language and ISA's is designed in such a way that they can support backward compatibility. But what confuses me here is stack calling conventions. These conventions differ a lot depending on the architecture. For example, in x86, in order to backup frame pointer, proceses pushes where it points to stack(RAM) and pops after it is done. On the other hand, in x86-64, processes doesn't need to update frame pointer at all since all the references is given via stack pointer. And secondly, While in x86 architecture arguments to functions is passed by stack in x86-64, registers are used for that purpose.
Maybe this differences between stack calling conventions of x86-64 and x64 architecture may not affect the way program stack grows as long as different conventions are not used at the same time and this is mostly the case because x32 functions are called by other x32's and same for x64. But, at one point, a function (probably a system function) will call a function whose code is compiled for a x86-64 machine with some arguments, at this point, I am curious about how OS(or some other control unit) handle to get this function work.
Thanks in advance.
Part of the way that the i386/x86-64 architecture is designed is that the CS and other segment registers refer to entries in the GDT. The GDT entries have a few special bits besides the base and limit that describe the operating mode and privilege level of the current running task.
If the CS register refers to a 32-bit code segment, the processor will run in what is essentially i386 compatibility mode. Likewise 64-bit code requires a 64-bit code segment.
So, putting this all together.
When the OS wants to run a 32-bit task, during the task switch into it, it loads a value into CS which refers to a 32-bit code segment. Interrupt handlers also have segment registers associated with them, so when a system call occurs or an interrupt occurs, the handler will switch back to the OS's 64-bit code segment, (allowing the 64-bit OS code to run correctly) and the OS then can do its work and continue scheduling new tasks.
As a follow up with regards to calling convention. Neither i386 or x86-64 require the use of frame pointers. The code is free to do as it pleases. In fact, many compilers (gcc, clang, VS) offer the ability to compile 32-bit code without frame pointers. What is important is that the calling convention is implemented consistently. If all the code expects arguments to be passed on the stack, that's fine, but the called code better agree with that. Likewise, passing via registers is fine too, just everyone has to agree (at least at the library interface level, internal functions can generally do as they please).
Beyond that, just keep in mind that the difference between the two isn't really an issue because every process gets its own private view of memory. A side consequence though is that 32-bit apps can't load 64-bit dlls, and 64-bit apps can't load 32-bit dlls, because a process either has a 32-bit code segment or a 64-bit code segment. It can't be both.
The processor in put into legacy mode, but that requires everything executing at that time to be 32bit code. This switching is handled by the OS.
Windows : It uses WoW64. WoW64 is responsible for changing the processor mode, it also provides the compatible dll and registry functions.
Linux : Until recently Linux used to (like windows) shift to running the processor in legacy mode when ever it started executing 32bit code, you needed all the 32bit glibc libraries installed, and it would break if it tried to work together with 64bit code. Now there are implementing the X32 ABI which should make everything run like smoother and allow 32bit applications to access x64 feature like increased no. of registers. See this article on the x32 abi
PS : I am not very certain on the details of things, but it should give you a start.
Also, this answer combined with Evan Teran's answer probably give a rough picture of everything that is happening.