I am currently building an Executable handling application in Objective C and I just wanna know a simple code that can determine if an executable file can be launched (without launching it) or if it is just a loadable one.
Thanks.
Once you've taken care of permission bits and whether the file is a Mach-O, there are three things you need to consider:
File type
CPU compatibility
Fat binaries
File type
Whether your Mach-O is an executable, dylib, kext, etc., can be determined from a field in its header.
From <mach-o/loader.h>:
struct mach_header {
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype; // <---
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
};
Also from <mach-o/loader.h> you get all possible values for that field:
#define MH_OBJECT 0x1 /* relocatable object file */
#define MH_EXECUTE 0x2 /* demand paged executable file */
#define MH_FVMLIB 0x3 /* fixed VM shared library file */
#define MH_CORE 0x4 /* core file */
#define MH_PRELOAD 0x5 /* preloaded executable file */
#define MH_DYLIB 0x6 /* dynamically bound shared library */
#define MH_DYLINKER 0x7 /* dynamic link editor */
#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
#define MH_DYLIB_STUB 0x9 /* shared library stub for static linking only, no section contents */
#define MH_DSYM 0xa /* companion file with only debug sections */
#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */
CPU compatibility
Just because it says "executable", doesn't mean it can be launched though. If you take an iOS app and try to execute it on your iMac, you'll get a "Bad CPU type in executable" error message.
The different CPU types are defined in <mach/machine.h>, but the only of comparing against the current CPU type is via defines:
#include <mach/machine.h>
bool is_cpu_compatible(cpu_type_t cputype)
{
return
#ifdef __i386__
cputype == CPU_TYPE_X86
#endif
#ifdef __x86_64__
cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64
#endif
#ifdef __arm__
cputype == CPU_TYPE_ARM
#endif
#if defined(__arm64__)
cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64
#endif
;
}
(This will only work if your application has 64-bit slices, so that it always runs as 64-bit when it can. If you want to be able to run as a 32-bit binary and detect whether a 64-bit binary could be run, you'd have to use sysctl on "hw.cpu64bit_capable" together with defined, but then it gets even uglier.)
Fat binaries
Lastly, your binaries could be enclosed in fat headers. If so, you'll simply need to iterate over all slices, find the one corresponding to your current architecture, and check the two conditions above for that.
Implementation
There is no Objective-C API for this that I know of, so you'll have to fall back to C.
Given a pointer to the file's contents and the is_cpu_compatible function from above, you could do it like this:
#include <stdbool.h>
#include <stddef.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
bool macho_is_executable(char *file)
{
struct fat_header *fat = (struct fat_header*)file;
// Fat file
if(fat->magic == FAT_CIGAM) // big endian magic
{
struct fat_arch *arch = (struct fat_arch*)(fat + 1);
for(size_t i = 0; i < fat->nfat_arch; ++i)
{
if(is_cpu_compatible(arch->cputype))
{
return macho_is_executable(&file[arch->offset]);
}
}
// File is not for this architecture
return false;
}
// Thin file
struct mach_header *hdr32 = (struct mach_header*)file;
struct mach_header_64 *hdr64 = (struct mach_header_64*)file;
if(hdr32->magic == MH_MAGIC) // little endian magic
{
return hdr32->filetype == MH_EXECUTE && is_cpu_compatible(hdr32->cputype);
}
else if(hdr64->magic == MH_MAGIC_64)
{
return hdr64->filetype == MH_EXECUTE && is_cpu_compatible(hdr64->cputype);
}
// Not a Mach-O
return false;
}
Note that these are still rather basic checks though, which will e.g. not detect corrupt Mach-O's, and which could easily be fooled by malicious files. If you wanted that, you would have to either emulate an operating system and launch the binary within, or get into the research field of theoretical IT and revolutionize the mathematics of provability.
My understanding is you want to distinguish a Mach-O standalone executable from a Mach-O dyld library. A standalone executable will use either:
LC_MAIN load command to denote the entry point, supported since MacOS 10.7
LC_UNIXTHREAD load command , older non-dyld approach to do the same (still supported)
A dyld library will not have either of these Mach-O load commands, so if you detect one of them it means it's a runnable standalone executable. That of course does not imply the binary executable is valid and kernel won't kill it for other reasons.
If you want inspect some test files to verify it I recommend using a free tool called MachOView
Related
I would like to know the proper procedure for calling a .dll file with also having a .cpp and .h files for a certain application. I have a program which is the .cpp file with different .h header files and I also included the .dll file into the folder where the .cpp and .h files are located. I would like to know in the .cpp code how am I able to call upon this .dll file since inside of it there are different functions that will allow a DDC264 Evaluation Board to read data from memory through usb and extract the data. I am using a program called DevC++ and I am receiving a current Error which is [Id] returned 1 exit status and MakefileWin has changed.
Attached below is a snippit of the .cpp code:
I also would like to know how to fix both of these errors .enter image description hereenter image description here
// USB_IO_for_VB6.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "USB_IO_For_VB6.h"
#include "CyAPI.h"
#include <cstring>
#include <malloc.h>
#include "BASETSD.H"
#include <math.h>
#include <stdio.h>
// #include <string.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
//int USB_IO_FOR_VB6_EXPORTS int USB_IO_for_VB6_API =22;
I
USB_IO_FOR_VB6_API int nUSB_IO_for_VB6 = 22;
#define STRINGLEN 65536 //the larger this number is, the faster the data is shifted in.
#define MAX_CHANNELS_FAST 4096 // 2048= 1024A + 1024B
#define DBP 0 //debug print - 1 enables writing some information to a file in "C:\temp\"
// This function reads the device descriptors from the Cypress USB Chip(s).
// It returns arrays of values, one set of values per device detected.
// The user can then use the visual basic software to select which device to use.
int __stdcall ReadDeviceDescriptors(int *USBdevCount, int *bLengthPass, int *bDescriptorTypePass,
long *bcdUSBPass, int *bDeviceClassPass, int *bDeviceSubClassPass,
int *bDeviceProtocolPass, int *bMaxPacketSize0Pass, long *idVendorPass,
long *idProductPass, long *bcdDevicePass, int *iManufacturerPass,
int *iProductPass, int *iSerialNumberPass, int *bNumConfigurationsPass)
{
CCyUSBDevice *USBDevice;
USB_DEVICE_DESCRIPTOR descr;
USBDevice = new CCyUSBDevice(NULL); // Create an instance of CCyUSBDevice
USBdevCount[0] = USBDevice->DeviceCount();
for (int i=0; i < USBDevice->DeviceCount(); i++)
{
if (USBDevice->Open(i))
{
USBDevice->GetDeviceDescriptor(&descr);
bLengthPass[i]=descr.bLength;
bDescriptorTypePass[i]=descr.bDescriptorType;
bcdUSBPass[i]=descr.bcdUSB;
bDeviceClassPass[i]=descr.bDeviceClass;
bDeviceSubClassPass[i]=descr.bDeviceSubClass;
bDeviceProtocolPass[i]=descr.bDeviceProtocol;
bMaxPacketSize0Pass[i]=descr.bMaxPacketSize0;
idVendorPass[i]=descr.idVendor;
idProductPass[i]=descr.idProduct;
bcdDevicePass[i]=descr.bcdDevice;
iManufacturerPass[i]=descr.iManufacturer;
iProductPass[i]=descr.iProduct;
iSerialNumberPass[i]=descr.iSerialNumber;
bNumConfigurationsPass[i]=descr.bNumConfigurations;
USBDevice->Close();
}
}
return( USBdevCount[0] );
}
I am not sure about how to go about calling a .dll file in C++, I am fairly new to Object Oriented programming.
Regarding the MakefileWin error I tried changing the TDM-GCC release version from 32 to 64 bits and the error continues.
I also tried deleting the dllmain.cpp which is another cpp file that is not needed and moving another original.cpp file from the folder that is shown in one of the images.
I only have a single .cpp file running on my DevC++ compiler which I thought would not cause the Error [Id] returned 1 to exit status to pop up.
I have a program using cpprestsdk for http querying and websocketpp for subscribing a data stream. The program will crash immediately(it says Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)). But if I comment either of the http querying or subcribing data stream, the program won't crash.
#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include "json.hpp"
#include <iostream>
#include <ctime>
#include <iostream>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <vector>
#include <string>
using std::string;
using namespace web;
using std::cout, std::endl;
using std::vector;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
void on_stream_data(websocketpp::connection_hdl hdl, message_ptr msg) {
}
class OrderBook {
public:
void initialize() {
web::http::client::http_client_config cfg;
std::string uri = string("https://fapi.binance.com/fapi/v1/depth?symbol=btcusdt&limit=1000");
web::http::client::http_client client(U(uri), cfg);
web::http::http_request request(web::http::methods::GET);
request.headers().add("Content-Type", "application/x-www-form-urlencoded");
web::http::http_response response = client.request(request).get();
}
int start_stream() {
client c;
std::string uri = string("wss://fstream.binance.com/ws/btcusdt#depth#100ms");
try {
c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
c.init_asio();
c.set_message_handler(bind(on_stream_data, ::_1, ::_2));
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
if (ec) {
std::cout << "could not create connection because: " << ec.message() << std::endl;
return 0;
}
c.connect(con);
c.run();
} catch (websocketpp::exception const &e) {
std::cout << e.what() << std::endl;
}
}
};
int main(int argc, char *argv[]) {
OrderBook ob;
ob.initialize(); // comment either of these two lines, the program won't crash, otherwise the program will crash once start
std::this_thread::sleep_for(std::chrono::milliseconds(10000000));
ob.start_stream(); // comment either of these two lines, the program won't crash, otherwise the program will crash once start
}
When I run this program in Clion debug mode, Clion show that the crash comes from function in /opt/homebrew/Cellar/boost/1.76.0/include/boost/asio/ssl/detail/impl/engine.ipp
int engine::do_connect(void*, std::size_t)
{
return ::SSL_connect(ssl_);
}
It says Exception: EXC_BAD_ACCESS (code=1, address=0xf000000000)
What's wrong with it? is it because I run two pieces of code using boost::asio, and something shouldn't be initialized twice?
I can compile this and run it fine.
My best bet is that you might be mixing versions, particularly boost versions. A common mode of failure is caused when ODR violations lead to Undefined Behaviour.
Note that these header-only libraries depend on a number of boost libraries that are not header-only (e.g. Boost System, Thread and/or Chrono). You need to compile against the same version as the libraries you link.
If you use distribution packaged versions of any library (cpprestsdk, websocketpp or whatever json library that is you're using) then you'd be safest also using the distribution packaged version of Boost.
I'd personally simplify the situation by just using Boost (Beast for HTTP/websocket, Json for, you guessed it).
Running it all on a test Ubuntu 18.04 the OS Boost 1.65 version, the start_stream sequence triggers this informative error:
[2022-05-22 13:42:11] [fatal] Required tls_init handler not present.
could not create connection because: Connection creation attempt failed
While being UBSAN/ASAN clean. Perhaps that error helps you, once you figure out the configuration problems that made your program crash.
I am creating a QR code scanner program in C++ using the library called libdecodeqr.
I downloaded all the files from https://github.com/josephholsten/libdecodeqr and I modified one of the test programs. However, I keep getting the error "unresolved external symbol". It's because I have not linked the libraries.
But I can't find libdecodeqr.lib anywhere! It's not included in the GitHub package and it's nowhere online!
In the instructions on the GitHub page, it says to add decodeqr.h, qrtypes.h, qrerror.h and libdecodeqr.lib to my environment. Other than the .lib file, I have added all those files to my environment.
Where can I find libdecodeqr.lib?
Also, here is the sample program I modified and am testing:
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "C:/Users/Asish/Documents/libdecodeqr-master/libdecodeqr/decodeqr.h"
#include "C:/Users/Asish/Documents/libdecodeqr-master/libdecodeqr/qrerror.h"
#include "C:/Users/Asish/Documents/libdecodeqr-master/libdecodeqr/qrtypes.h"
#include "bitstream.h"
using namespace cv;
int main(int argc, char *argv[])
{
namedWindow("src", 1);
//
// load image
//
Mat src_old = imread("qrTest.png", 1);
IplImage* src = new IplImage(src_old);
imshow("src", src_old);
//
// show version info
//
printf("libdecodeqr version %s\n", qr_decoder_version());
//
// initialize
//
QrDecoderHandle decoder = qr_decoder_open();
//
// do decode using default parameter
//
short stat = qr_decoder_decode_image(decoder, src);
printf("STATUS=%04x\n", stat);
//
// get QR code header
//
QrCodeHeader header;
if (qr_decoder_get_header(decoder, &header)){
//
// get QR code text
// To null terminate, a buffer size is larger than body size.
//
char *buf = new char[header.byte_size + 1];
qr_decoder_get_body(decoder, (unsigned char *)buf, header.byte_size + 1);
printf("%s\n", buf);
}
//
// finalize
//
qr_decoder_close(decoder);
puts("");
puts("Hit any key to end.");
cvWaitKey(0);
destroyAllWindows();
cvReleaseImage(&src);
return(0);
}
You are downloading the source code from GitHub, which means that you also need to create a new VisualStudio C++ project to compile your own libdecodeqr.lib (or dll). This will require you also install OpenCV in your computer.
I have created a GUI using tcl. I want to make some of the core functionalities of the tcl code available to be used by any program which supports dll. For that i have taken a very simple tcl code example, which adds two integer numbers and i have written a c wrapper function to use this functionality. This is working for me. Now how can i create a dll for these two c and tcl files, so that any program can use this addition functionality by simply loading the dll.
Here is my simple tcl code :
/* Filename : simple_addition.tcl */
#!/usr/bin/env tclsh8.5
proc add_two_nos { } {
set a 10
set b 20
set c [expr { $a + $b } ]
puts " c is $c ......."
}
And here is my c wrapper function which uses the above tcl addition functionality :
#include <tcl.h>
#include <tclDecls.h>
#include <tclPlatDecls.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
Tcl_Interp *interp;
int code;
char *result;
printf("inside main function \n");
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
code = Tcl_Eval(interp, "source simple_addition.tcl; add_two_nos");
/* Retrieve the result... */
result = Tcl_GetString(Tcl_GetObjResult(interp));
/* Check for error! If an error, message is result. */
if (code == TCL_ERROR) {
fprintf(stderr, "ERROR in script: %s\n", result);
exit(1);
}
/* Print (normal) result if non-empty; we'll skip handling encodings for now */
if (strlen(result)) {
printf("%s\n", result);
}
/* Clean up */
Tcl_DeleteInterp(interp);
exit(0);
}
This c wrapper is working fine for me and gives correct results.
Now I want to create a dll file, so that if i include that dll to any program that supports dll, it should be able to use this addition functionality of the above tcl code. Can anybody please tell me the way i can do it. Please help me. I am new to this dll concept.
In order to create the .dll you'll have to use something like Visual Studio and C or C++ to create the .dll (there are lots of other tools out there that can create .dll files but VS is easy to get hold of and to use.) So in VS create a new project, this needs to be a C++ WIN32 project. Select the DLL application type and the Export Symbols additional option.
VS will create a basic .dll that you can then amend to do what you want. I short I'd look at putting the creating/destruction of the intrepter into the dllmain:
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
Tcl_FindExecutable(NULL);
interp = Tcl_CreateInterp();
}
case DLL_THREAD_ATTACH:
break ;
case DLL_THREAD_DETACH:
break ;
case DLL_PROCESS_DETACH:
{
Tcl_DeleteInterp(interp);
break;
}
}
return TRUE;
}
and then create functions exported by the .dll that make use of the interpreter. If you aren't familiar with the concept of shared libaries then I'd suggest spending a little time reading up on them, try here and here for some background reading.
I want to write a little Linux Kernel Module that can show me the PID of all running processes.
I have the following code:
/*
* procInfo.c My Kernel Module for process info
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
/*
* The init function, called when the module is loaded.
* Returns zero if successfully loaded, nonzero otherwise.
*/
static int mod_init(void)
{
printk(KERN_ALERT "ProcInfo sucessfully loaded.\n");
return 0;
}
/*
* The exit function, called when the module is removed.
*/
static void mod_exit(void)
{
printk(KERN_ALERT "ProcInfo sucessfully unloaded.\n");
}
void getProcInfo()
{
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
}
module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rodrigo");
As you can see, i know i have to use the *struct task_struct* structure to get the PID and the Process name, but i am using current, and i know the existance of some double linked circular list that contains all PCB's, so the main question is:
what do i need to add to iterate over this linked lisk with p-next_task and p-prev_task so getProcInfo works?
Thanks!
The following macros from include/linux/sched.h may be useful:
#define next_task(p) \
list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
You probably need to hold the tasklist_lock before calling these macros; several examples of how to lock, iterate, and unlock, are in mm/oom_kill.c.
Actually, for newer kernels (2.6.18 and newer) the proper way to list tasks is by holding an rcu lock, because task list is now an RCU list. Also tasklist_lock is no more exported symbol - it means that when you are compiling a loadable kernel module, this symbol will not be visible for you.
example code to use
struct task_struct *task;
rcu_read_lock();
for_each_process(task) {
task_lock(task);
/* do something with your task :) */
task_unlock(task);
}
rcu_read_unlock();
Also documentation about RCU in linux kernel source directory can be helpful and you will find it in Documentation/RCU