I have quite low experience with Objective C as I started learning iOS development using Swift and I need to use a older ObjC library.
My netsdk.h library (file has over 50k lines)
#ifndef DHNETSDK_H
#define DHNETSDK_H
#if (defined(WIN32) || defined(_WIN32) || defined(_WIN64))
...
#else //non-windows
#define CLIENT_NET_API extern "C"
#define CALL_METHOD
#define CALLBACK
...
Basically after reading some problems related to this one I think there is problem with extern "C" on the next line
...
#define CLIENT_NET_API extern "C"
...
Due to this I am getting errors on many lines that use CLIENT_NET_API like
expected identifier or '('
Expanded from macro 'CLIENT_NET_API'
My first try was to wrap #define CLIENT_NET_API extern "C"
into
#ifdef __cplusplus
extern "C" {
#endif
#define CLIENT_NET_API
#ifdef __cplusplus
}
#endif
but then I am getting error "C does not support default arguments" on all lines using CLIENT_NET_API
for example these
CLIENT_NET_API BOOL CALL_METHOD CLIENT_StartBackUpCase(LLONG lLoginID, const NET_IN_START_CASE_BACK_UP* pstInParam, NET_OUT_START_CASE_BACK_UP *pstOutParam, int nWaitTime = NET_INTERFACE_DEFAULT_TIMEOUT);
CLIENT_NET_API BOOL CALL_METHOD CLIENT_StopBackUpCase(LLONG lLoginID, const NET_IN_STOP_CASE_BACK_UP* pstInParam, NET_OUT_STOP_CASE_BACK_UP *pstOutParam, int nWaitTime = NET_INTERFACE_DEFAULT_TIMEOUT);
I think it should be wrapped in some other way but I couldn't find a example with #define and extern keywords on the same line
In this case:
define CLIENT_NET_API extern "C"
Says, let CLIENT_NET_API be extern "C"
So, in your case you just define as empty existed preprocessor variable
#ifdef __cplusplus
extern "C" {
#endif
#define CLIENT_NET_API
#ifdef __cplusplus
}
#endif
PT_DENY_ATTACH is an anti-debugging feature that helps prevent debuggers from attaching to the app. Following code can be implemented in main() to prevent GDB from attaching to the application. :
#import <dlfcn.h>
#import <sys/types.h>
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#define PT_DENY_ATTACH 31
void disable_gdb() {
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
}
int main(int argc, char *argv[]) {
#autoreleasepool {
#ifdef DEBUG
//do nothing
#else
disable_gdb();
#endif
}}
Guys it is true that this trick has been worked around and can be bypassed by overriding but have a look at that
Here the guys from iphonedevwiki.net are showing another way to implement the same thing in assembly, making it much harder to be patched. So to bypass this assembly implementation one has to have the Mach-O binary decrypted and override the implementation of the function, for example an attacker could swap all assembly instructions from the function with only nop instructions which do nothing. But if you obfuscate your assembly routine, it will be much harder for attacker to recognise what is happening, so only the most experienced folks will be able bypass that.
For those of you who don't know how to write assembly in Swift 5 project, here is what you will need to do:
Create a new C File + Header
lets name them disable_debuggers_advanced.c and disable_debuggers_advanced.h
In disable_debuggers_advanced.c add the following:
#include "disable_debug_advanced.h"
void mRiYXNnZnZmZGF2Ym() {
// No Need to encode these strings, because they will be directly compiled, they are not going to be present in the 'DATA' segment of the binary.
__asm (
"mov r0, #31\n" // set #define PT_DENY_ATTACH (31) to r0
"mov r1, #0\n" // clear r1
"mov r2, #0\n" // clear r2
"mov r3, #0\n" // clear r3
"mov ip, #26\n" // set the instruction pointer to syscal 26
"svc #0x80\n" // SVC (formerly SWI) generates a supervisor call. Supervisor calls are normally used to request privileged operations or access to system resources from an operating system
);
}
In disable_debuggers_advanced.h add the following:
#ifndef disable_debug_advanced_h
#define disable_debug_advanced_h
#include <stdio.h>
/**
Original name: `disable_gdb_advanced()`
This function makes the process deny the attaching request by debugers by
simulating what is already available on macOS:
ptrace(PT_DENY_ATTACH, 0, 0, 0);
by implementing it directly in assembly language.
This method of disabling debugers is well known to attackers but there is nothing they can do to easily bypass it
because it is a part of the kernel memory space.
Please note that this will make XCode not being able to attach its debuger to the process too,
so run it only in release builds.
source: https://iphonedevwiki.net/index.php/Crack_prevention#PT_DENY_ATTACH
*/
void mRiYXNnZnZmZGF2Ym(void) __attribute__((always_inline));
#endif /* disable_debug_advanced_h */
Add #include "disable_debug_advanced.h" to your bridging header and a bridging header if your project does not already have one.
Now you can call this function to disable debuggers.
Note that this will break even the XCode debugger, so use it only on release builds
If you are wondering about the __attribute__((always_inline)) part and the weird name it is because we want our function to be hidden as much as possible. If you are not familiar with function inlining, you can watch my video about function inlining here where i describe it in depth or you can read in wikipedia about it. Even thought it is a speed compiler optimisation, it could give us benefits here because if you call it from multiple locations it will be harder for attacker to patch all function body copies in the app.
And the name is written like this, because this inlining is just a hint to the compiler, it is not guaranteed that it will happen. And if it does not happen and our function for disabling the debugger is clearly defined in the TEXT segment of our binary, we want it to be at least with obfuscated name, so that no one could guess what it does just by reading its assembly label.
In my opinion one should call this as a top level function even before the UIApplication object is created.
In order to do that:
Add a new file to your Swift project and name it 'main.swift' (NAME IS IMPORTANT)
Remove the #UIApplicationMain tag from your AppDelegates class definition.
In your main.swift file write the following:
mRiYXNnZnZmZGF2Ym() // disable debuggers
// initialises the UIApplication and fires the event loop.
// This function never returns!
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
If you want to see a video of how to execute top level code in main.swift, you can see me doing it on this video
In attempt to make it even more obfuscated and harder to crack, one could use assembly obfuscators like this one Movfuscator so that only a few people would be able to recognise what these assembly instructions mean.
Note: according to the wiki page of this tool, it has been workearound and must not be used:
IMPORTANT NOTE: This trick has been worked around by pirates. Don't rely on it!
Assuming you are referring to a Hybrid application created in MobileFirst Studio 7.1 - this, well, is not different than any other iOS app.
The end result of a Hybrid app, is still an Xcode project that you open in Xcode in order to build the application. This means then that you need to place your code in the same place in the Xcode project as if this was a regular Xcode project (which, it is), per the wiki page for PT_DENY_ATTACH.
As noted by #Idan Adar - this trick is workedAround, but in case u want to try it in any education or some other purpose u can try do following:
add define for u'r app to allow u run and debug if needed
#define SOME
add following code in main.m
#define SOME
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#ifdef SOME
#import <dlfcn.h>
#import <sys/types.h>
typedef int (*ptrace_ptr_t)(int request, pid_t pid, caddr_t addr, int data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif // !defined(PT_DENY_ATTACH)
void disable_gdb();
int main(int argc, char *argv[])
{
// disable_gdb();
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
void disable_gdb()
{
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
}
int main3(int argc, char *argv[])
{
return -1;
}
#else
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
#endif
Here - some good points to start about
I saw this question has not marked correct answered yet. I already use below code block to use anti-debugging. Please open your main.m file to added below code snipped.
#import "AppDelegate.h"
#import "Application.h"
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
#include <stdlib.h>
typedef int (*PYStdWriter)(void *, const char *, int);
static PYStdWriter _oldStdWrite;
#define PT_DENY_ATTACH 31
int __pyStderrWrite(void *inFD, const char *buffer, int size)
{
if ( strncmp(buffer, "AssertMacros:", 13) == 0 ) {
return 0;
}
return _oldStdWrite(inFD, buffer, size);
}
static int is_debugger_present(void)
{
int name[4];
struct kinfo_proc info;
size_t info_size = sizeof(info);
info.kp_proc.p_flag = 0;
name[0] = CTL_KERN;
name[1] = KERN_PROC;
name[2] = KERN_PROC_PID;
name[3] = getpid();
if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {
perror("sysctl");
exit(-1);
}
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
int main(int argc, char *argv[]) {
#ifdef DEBUG
_oldStdWrite = stderr->_write;
stderr->_write = __pyStderrWrite;
#autoreleasepool {
return UIApplicationMain(argc, argv, NSStringFromClass([Application class]), NSStringFromClass([AppDelegate class]));
}
#else
//Anti Debugging Code
//https://coredump.gr/articles/ios-anti-debugging-protections-part-2/
//ptrace(PT_DENY_ATTACH, 0, 0, 0);
printf("Looping forever");
fflush(stdout);
while (1)
{
sleep(1);
if (is_debugger_present())
{
//[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isAntiDebug"];
printf("Debugger detected! Terminating...\n");
return -1;
}
printf(".");
fflush(stdout);
_oldStdWrite = stderr->_write;
stderr->_write = __pyStderrWrite;
#autoreleasepool {
//[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"isAntiDebug"];
int retVal = UIApplicationMain(argc, argv, NSStringFromClass([Application class]), NSStringFromClass([AppDelegate class]));
return retVal;
}
}
#endif
}
As pointed out by Stoyan. Your implementation could be easily bypassed. You should add an assembly code. Just one missing thing from the above answer is that you have to add arm64 macro or you will not be able to build your project on simulators (OS X are using x86_64 arch)
So add this:
#if defined (__arm64__)
__asm(
"mov x0, #26\n" // ptrace
"mov x1, #31\n" // PT_DENY_ATTACH
"mov x2, #0\n"
"mov x3, #0\n"
"mov x16, #0\n"
"svc #128\n"
);
I wrote a simple guide for this. Check it out
I have problem with Xcode, I am getting following error when running the code:
Error : Expected identifier or ')'
Here is th code:
#import "IOKitLib.h"
#import <dlfcn.h>
#import <pthread.h>
#import <mach/mach.h>
#import <sys/ptrace.h>
#import <libkern/OSAtomic.h>
static mach_port_t masterPort = 0;
extern "C" kern_return_t io_service_open_extended
(
mach_port_t service,
task_t owningTask,
uint32_t connect_type,
NDR_record_t ndr,
io_buf_ptr_t properties,
mach_msg_type_number_t propertiesCnt,
kern_return_t *result,
mach_port_t *connection
);
Please help me to solve this problem and let me know where am I doing wrong. Thanks !
extern "C" is valid in C++ only. You can make the declaration usable in any language (C++, C or Objective-C), from a header file for example, using the __cplusplus guard macro:
#ifdef __cplusplus
extern "C" {
#endif
kern_return_t io_service_open_extended
(
mach_port_t service,
task_t owningTask,
uint32_t connect_type,
NDR_record_t ndr,
io_buf_ptr_t properties,
mach_msg_type_number_t propertiesCnt,
kern_return_t *result,
mach_port_t *connection
);
#ifdef __cplusplus
}
#endif
I think this is a very simple thing to do, but since I'm new to iOS development and objective C, I can't figure it out.
#define RESTFUL_PATH_PREFIX #"https://gogch.com/gch-restful";
#define LOGIN RESTFUL_PATH_PREFIX #"/login;
I want the result "https://gogch.com/gch-restful/login"
but I'm getting the result as "https://gogch.com/gch-restful"
other topics in stackoverflow mention only about adding a new string to the beginning of a string like,
#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
Remove the trailing semi-colon:
#define RESTFUL_PATH_PREFIX #"https://gogch.com/gch-restful";
^
and then string constants can be concatenated by the compiler:
#"first" #"second"
instead of:
#"first"; #"second"
It is much better practice to use constants instead of define macros.
static NSString *const YourPath = #"https://...";
And then you can concatenate your strings with NSString stringWithFormat: method.
Since I made this answer to a question marked as a dupe, I'll also answer it here
Sure, you can use defines OR you can use NSString constants. It's really a matter of preference ... I have however seen both a #define and an NSString const * const being used before. Defines are easier, and you're probably not going to save that much memory by having constants instead of individual immutable instances of NSString all over the place.
Some advice is to think about how you export the NSString constants. You'll probably want EXTERN_PRIVATE instead of EXTERN, but my sample code will allow all clients of your header to read the string constants you've declared therein.
What you can do:
Create a new .m/.c file with a header in Xcode
In the .m/.c file, declare and initialise your constants
Export the constant as necessary so other compilation units can access it
constants.h
#ifndef constants_h
#define constants_h
// Export the symbol to clients of the static object (library)
#define EXTERN extern __attribute__((visibility("default")))
// Export the symbol, but make it available only within the static object
#define EXTERN_PRIVATE extern __attribute__((visibility("hidden")))
// Make the class symbol available to clients
#define EXTERN_CLASS __attribute__((visibility("default")))
// Hide the class symbol from clients
#define EXTERN_CLASS_PRIVATE __attribute__((visibility("hidden")))
#define INLINE static inline
#import <Foundation/Foundation.h>
EXTERN NSString const * _Nonnull const devBaseUrl;
#endif /* constants_h */
constants.m
#include "constants.h"
NSString const * _Nonnull const devBaseUrl = #"http://127.0.0.1:8000/";
main.m
#import <Foundation/Foundation.h>
#import "constants.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSLog(#"Constant value: %#", devBaseUrl);
// Prints: Constant value: http://127.0.0.1:8000/
}
return 0;
}
I have the following code that I want to run on Iphone OS, what compiler flag should I use for IOS and where in the below code should it be inserted? Thanks
#if defined(__BORLANDC__) || defined (__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__) || defined(__HIGHC__) || defined(_TURBOC_)
typedef long int Word32 ;
typedef short int Word16 ;
typedef short int Flag ;
#elif defined( __sun)
typedef short Word16;
typedef long Word32;
typedef int Flag;
#elif defined(__unix__) || defined(__unix)
typedef short Word16;
typedef int Word32;
typedef int Flag;
#elif defined(VMS) || defined(__VMS)
typedef short Word16;
typedef long Word32;
typedef int Flag;
#else
#error COMPILER NOT TESTED typedef.h needs to be updated, see readme
#endif
For iOS/tvOS/watchOS, you can use:
#if (TARGET_OS_IPHONE)
For iOS, you can use:
#if (TARGET_OS_IOS)
and for MAC OS X:
#if (TARGET_OS_OSX)
Hope this helps.