I tried to use CryptoObfuscator to obfuscate my Android app, but it doesn't generate all the pdb files.
My Xamarin.Forms solution has 11 projects, 7 of them should be obfuscated. I disabled most CryptoObfuscator features just to test it. My .obproj file contains these settings for all dlls:
<Assembly Load="true" Path=".\bin\Release\RoyalMobileApps.XF.dll" XapEntryName="" KeyFilePath="" KeyFileContainsPublicKeyOnly="False" CertFilePath="" TimeStampURL="" Rfc3161TimestampURL="False" SHA256SigningAlgorithm="False" Embed="True" AddExceptionReporting="False" PfxPassword="" PfxPasswordCert="" IsWinRTAssembly="False">
<ObfuscationSettings EncryptStrings="True" EncryptMethods="False" EncryptConstants="False" SuppressReflector="False" ReduceMetaData="False" ObfuscationDisposition="1" FlowObfuscation="2" CodeMasking="0" SuppressILDASM="True" SuppressReflection="False" CombineResources="True" EncryptResources="True" CompressResources="True" MarkAsSealed="False" EnableTamperDetection="False" EnableAntiDebugging="False" SymbolRenaming="True" HideExternalCalls="False" HideInternalCalls="False" GeneratePdbFile="True" ObfuscatePdbFileNames="True" IncludeLocalVariablesInPdbFile="False" Encrypt="False" Compress="False" MSBuild="False" ObfuscatedNamespace="A" RetainNamespace="False" ModuleInitializationMethod="" LicensingMerge="False" RemoveConstants="False" ProcessSatelliteAssemblies="True">
<Watermarks Watermark0="" Watermark1="" Watermark2="" Watermark3="" Watermark4="" Watermark5="" Watermark6="" Watermark7="" Watermark8="" Watermark9="" />
</ObfuscationSettings>
</Assembly>
As you can see I set GeneratePdbFile="True" for all 7 projects. I integrated co.exe in my build process and it claims to have run successfully. It generates 7 dlls but only 6 pdbs. The pdb file for my main PCL project which I pasted above is missing and therefore Xamarins linker fails and I cannot build an apk.
How can I get CryptoObfuscator to create all pdbs? Or can I generate the apk without them?
Unfortunately the CryptoObfuscator support did not respond to my emails and I couldn't find anybody else with a similar problem.
I got it working by disabling the Pdbs at all. I switched to release mode and opened up the properties of each project which should be obfuscated. In Build / Advanced you can set the Debug Info to None.
In Crypto Obfuscator I disabled Output Settings / Generate New Pdb File For Assembly.
Then nothing created Pdb files. I got warnings when building the solution, but they can be ignored.
This answer should actually be credited to #JonDouglas, but he wrote only a comment.
Unfortunately I had to disable Rename Symbols too. But this was the main reason why I wanted to use Crypto Obfuscator. Because I couldn't get the Name Protection in ConfuserEx running. So as it doesn't work in either tool and Crypto Obfuscators support still didn't answer my email I'm back to ConfuserEx. This is free and it cannot be deobfuscated with de4dot.
Related
I have some code that is written in Java and Kotlin for Android; the Java part can be translated into Kotlin using the Android Studio. Most of this code is business; that means, independent on any hardware or platform specifics; some Android specific classes (like "Bitmap") can be replaced by abstract or general self-defined classes.
As already known, Kotlin business code can be used in multiplatform applications for Android and iOS. Description here : https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html .
Xamarin is used for multiplatform apps, too.
On the other hand, there is a way to include Kotlin code in Xamarin projects. For this purpose, the Xamarin.Kotlin.StdLib is used : https://libraries.io/nuget/Xamarin.Kotlin.StdLib .
My question: Is it possible to develop a Xamarin project (maybe with Xamarin Forms) that includes the Kotlin business code and will work in both Android and iOS environments?
Here are some instructions.
ANDROID STUDIO
Create a new Project: "File -> New -> New Module -> Kotlin
Multiplatform Shared Module".
Follow these instructions:
https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html
until "Run your cross-platform application on Android".
For Android we're finished. Following steps are only for iOS.
We now assume that there is a module with the name "shared". If this module has another name, please replace it in the following instructions.
XCODE:
The following instructions are similar to that in https://kotlinlang.org/docs/multiplatform-mobile-integrate-in-existing-app.html#make-your-cross-platform-application-work-on-ios . The difference is that we don't want to build the app now, but a framework.
File New - Project.
Select the template for "Framework" and click "Next".
Choose a product name (for example, "KmmExample"). Language:
Objective C
Build Phases - New Run Script Phase:
cd "$SRCROOT/.."
chmod +x gradlew
./gradlew :shared:embedAndSignAppleFrameworkForXcode
Move the Run Script phase up so that it is located after the
"Dependencies" item.
On the Build Settings tab, switch to "All" build settings.
In the Search Paths paragraph, specify the Framework Search Path for both Debug and Release:
$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)
In the Linking paragraph:
Specify the "Mach-O Type" as "Static Library".
Specify the Other Linker Flags as
$(inherited) -framework shared
In the Architectures paragraph, "Architectures" may be unchanged or changed to "$(ARCHS_STANDARD_INCLUDING_64_BIT)".
Build the project.
If successful, there will be a folder structure inside "shared/build". There will be a subfolder "xcode-frameworks". In the "Debug" resp. "Release" directory, there will be subfolder(s) with the name(s) of the iOS device(s) or simulator(s). For example, "iphonesimulator15.5". It contains another subfolder: "shared.framework". In the "Headers" you find a "shared.h", and there is the library itself: "shared". (In the "shared/build" folder there will be also a "bin" directory with device and simulator names containing "debugFramework" and similar structures inside.)
OBJECTIVE SHARPIE
Download the "Objective Sharpie" tool
(https://learn.microsoft.com/en-us/xamarin/cross-platform/macios/binding/objective-sharpie/)
In order to create "ApiDefinitions.cs" from shared.h using
"sharpie" follow these steps:
Open a Termimal (Command-line) session.
Change to the directory where "shared" is located.
Type:
sharpie bind --output=./SharpieOutput --namespace=Shared --sdk iphoseos15.5 -scope ./shared ./shared/build/xcode-frameworks/Debug/iphonesimulator15.5/shared.framework/Headers/shared.h
(please replace "iphoneos15.5" by the correct SDK and "Debug/iphonesimulator15.5" by the correct folder name)
You also can choose another namespace instead of "Shared". It will be specified in the ApiDefinitions.h.
If successful, a "ApiDefinitions.cs" will be in a new subfolder
"SharpieOutput".
VISUAL STUDIO / XAMARIN
Use Visual Studio 2019 or 2022 or higher.
Create a new Solution, say, "MyApp".
"MyApp" should contain four projects: "MyApp", "MyApp.Android",
"MyApp.iOS".
Here, we don't talk about "MyApp.Android".
Right-click on the solution name and add a "New Project". Choose "iOS - Library - Bindings Library". Its name may be "MyApp.iOS.Binding".
Replace the ApiDefinitions.cs by that that has been created in the precding step.
Add the "shared" library (created by XCode in one of the steps above) as a "Native Library".
Right-click on ApiDefinitions.cs and change "Build action" =
"ObjcBindingApiDefinition".
When you now open ApiDefinitions.cs, you'll probably see a lot of errors and marked lines. They may be handled as follows:
For the "[Verify]" attribute, please check here: https://learn.microsoft.com/en-us/xamarin/ios/platform/binding-swift/walkthrough#build-a-binding-library , section 5.
If "NativeHandle" creates a compiler error, please add at the top:
#if !NET
using NativeHandle=System.IntPtr;
#endif
You may remove "using" with the shared module ("using shared")
If you encounter errors like "Cannot declare instance members in a static class (CS0708) and "static classes cannot implement interfaces" (CS0714): try to comment out or remove the attribute "[Category]".
"[Unavailable (PlatformName.Swift)]" may be removed if yielding an error.
Handle typed classes resp. Interfaces with "<T>". For example, the "<T>" attribute should be added to some interfaces representing typed classes. In some cases special handling is necessary.
CS0246: In some cases, when an element cannot be found, an attribute "[BaseType(typeof(SharedBase))]" may help (assuming that the interface SharedBase is defined at the beginning of this file).
If, during a build run, there are warnings CS8767 ("… hides inherited member"), add the attribute [Override] above these members. For "New()", however, add "[New]" instead.
In case of linker errors MT5211 "Native linking failed, undefined Objective-C class …", add the attribute "[Protocol]" in front of the interface definition:
[BaseTye (typeof (NSObject))]
[Protocol]
public interface MyInterface { … }
Other compiler / linker errors (e.g. " … was built for newer iOS version (…) than being linked …" possibly can result in warnings after that.
The "MyApp" project contains all platform independent code. Those classes which contain platform dependent parts should be defined as interfaces.
"MyApp.Android" and "MyApp.iOS" should implement these interfaces. For "MyApp.iOS", "MyApp" and "MyApp.iOS.Binding" should be added as References. The classes implementing those interfaces now can use the interfaces defined in ApiDefinitions.h.
End of instructions.
I have posted the same question in another forum - https://learn.microsoft.com/en-us/answers/questions/875957/use-business-code-for-android-and-ios-written-in-k.html - and I have posted a possible answer, see the answer of Jul 19, 2022. Spoiler: yes, it is possible, but not directly, and it is complicated.
In my Ionic 5 app, I am using the capacitor-community/sqlite plugin. I am successfully able to create and use an encrypted db with this plugin. To use encryption a secret is required and the following is maintained in the official documentation as of today.
Defining your own secret and newsecret keys (encryption only)
in IOS, go to the Pod/Development Pods/capacitor-sqlite/GlobalSQLite.swift file
in Android, go to capacitor-sqlite/java/com.jeep.plugin.capacitor/cdssUtils/GlobalSQLite.java
and update the default values before building your app.
in Electron, go to YOUR_APP/electron/plugins/plugin.js-xxxx.js and search for class GlobalSQLite and modify the this.secretand
this.newsecret parameters.
I have searched for files GlobalSQLite.swift and GlobalSQLite.java in IOS and android respectively but there are no such files present. Also, the file paths are not available. I am not sure how to get these files to set my secret in the app. Please help.
You should look for the GlobalSQLite.java in node_modules\#capacitor-community\sqlite\android\src\main\java\com\getcapacitor\community\database\sqlite\SQLite. After changing the secrets you may need to sync the platforms with ionic cap sync.
The iOS and Electron files you also find there
I have an Android native library (C++ code base) called:
libserverapp.so
And I cannot get the Android build to find it:
"DllNotFoundException: serverapp"
I am using an internal build system, but when I parse the output of the build process, I can see many calls of the form:
android-ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/arm-linux-androideabi-g++.exe -march=armv7-a
After building my Android app, I inspect the resulting APK (renaming to .zip and extracting), and can see my library file here:
lib/armeabi-v7a/libserverapp.so
I can confirm that "ARMv7" is the target architecture in the Android Player settings, and I access the library, in C#, via:
[DllImport("serverapp", CallingConvention = CallingConvention.Cdecl)]
private static extern void run_sim(StringBuilder matchInput, StringBuilder results, int randomSeed);
I have built a Windows DLL of the C++ code, to use in the Editor, and everything works great. However, when I move to Android, the .so cannot be found. The import settings for libserverapp.so are:
Platform: Android; CPU: ARMv7; Path: Assets/Plugins/Android/libserverapp.so; Type: Native
Given that the final APK includes the .so where I expect it to be (lib/armeabi-v7a/), I assume my Unity settings are correct? Also, I am not using IL2CPP for the Android build.
Finally, when I do an object dump of the library file (using arm-linux-androideabi-objdump.exe), the file format of the library file is "elf32-littlearm".
I feel that the issue here is simply finding the .so, not the functionality within it. Any ideas on what's going on here?
Thanks!
I ended up solving the problem. I mentioned that was using an internal build system. Well, there seems to be a bug in it. I ported things over to official Android NDK makefiles, and then it "just worked". So in this case, the library could be found, but its contents weren't valid.
I use add_qt_android_apk to build an APK using Qt 5:
add_qt_android_apk(my_app_apk gustavsfairyland NAME "#string/ApplicationName"
DEPENDS
${QTAV_LIBRARIES}
)
QTAV_LIBRARIES is defined before:
set(QTAV_LIBRARIES
"${QTAV_FFMPEG_LIB_DIR}/libavcodec.so"
"${QTAV_FFMPEG_LIB_DIR}/libavfilter.so"
"${QTAV_FFMPEG_LIB_DIR}/libavformat.so"
"${QTAV_FFMPEG_LIB_DIR}/libavresample.so"
"${QTAV_FFMPEG_LIB_DIR}/libavutil.so"
"${QTAV_FFMPEG_LIB_DIR}/libswresample.so"
"${QTAV_FFMPEG_LIB_DIR}/libswscale.so"
"${CMAKE_BINARY_DIR}/buildqtav/${QTAV_LIB_DIR}/libQtAV.so"
"${CMAKE_BINARY_DIR}/buildqtav/${QTAV_LIB_DIR}/libQtAVWidgets.so"
)
I build libQtAV.so using the debug mode (user.conf):
CONFIG += no_config_tests
CONFIG += config_avutil config_avformat config_avcodec config_swscale config_swresample
CONFIG -= release
CONFIG += debug
When I use nm to check for symbols I get many symbols:
nm ../buildqtav/lib_android_arm/libQtAV.so
00062884 t $a
00061d88 t $a
0005f9d0 t $a
...
But when I use nm on the copied library in the libs directory I get nothing:
bash-4.3$ nm armeabi-v7a/libQtAV.so
nm: armeabi-v7a/libQtAV.so: no symbols
Does add_qt_android_apk remove the debugging symbols?
In the CMake module for Qt APK I found this:
if(EXTRA_LIBS)
set(EXTRA_LIBS "${EXTRA_LIBS},${LIB}")
else()
set(EXTRA_LIBS "${LIB}")
endif()
endforeach()
set(QT_ANDROID_APP_EXTRA_LIBS "\"android-extra-libs\": \"${EXTRA_LIBS}\",")
so it uses the specified external .so path. It is then added to qtdeploy.json in the CMake variable QT_ANDROID_APP_EXTRA_LIBS. Which has the entry
buildandroidarmeabi-v7a/buildqtav/lib_android_arm/libQtAV.so
in "android-extra-libs":
So it actually has the correct entry but somehow strips the debug symbols. The library in the "libs" folder has a size of 1.1 MiBytes while the original library in "lib_android_arm" has a size of 1.6 MiBytes.
I'd like to see the routines using ndk-stack which prints at the moment:
Stack frame #05 pc 000b714f /data/app/org.qtproject.gustavsfairyland-1/lib/arm/libQtAV.so: Routine ??
edit:
I use the following CMake module: https://github.com/LaurentGomila/qt-android-cmake
edit2:
It looks like androiddeployqt does always strip symbols of the libraries:
http://code.qt.io/cgit/qt/qttools.git/tree/src/androiddeployqt/main.cpp
stripLibraries() is always called when building the application.
As already mentioned in the edited question and in the answer, androiddeployqt is what strips the debuginfo from the .so file.
I belive the important point here is that androiddeployqt does not modify the file, it creates a copy in the process of generating the apk, and only this copy has the debug infos stripped. In the build output there is still the unmodified .so file which contains the debug infos and which can be used to debug the application (Qt creator does that AFAIK) and which can be used to grab symbol information - I use this for creating readable stacktraces with breakpad crashdump files.
I believe that's also the reason why QTBUG-57771 was rejected as incomplete: The Qt maintainers see no good reason to have the symbols available on the device, as long as debugging the application with Qt creator works with the current build process (and demonstrates that debugging is possible with a properly configured toolchain).
Well, androiddeployqt does ALWAYS strip the libraries to reduce their size. I have opened a bug report for Qt: https://bugreports.qt.io/browse/QTBUG-57771
Getting "system.entrypointnotfoundexception: loadlibrary" While trying to use SevenZipLib.dll to uncompress the .7z file containing media contents/file in the Android evn.
Context:
-The whole program is written in c# as a MONO Android Project. No Build/Deployment Error/warnings.
While running the apk, its throwing "system.entrypointnotfoundexception: loadlibrary".
-Also tested the same code as windows project (not mono) - uncompressing in the windows evn.
Assumptions for the issue:
7zip internally might be using COM components & Mono frame work is not supporting.
Question:
Has anyone come across similar issue? Please suggest some alternative dll/framework which can be used by my apk for uncompressing the .7z file.
Assuming that SevenZipLib.dll is the SevenZipLib Library on CodePlex, the problem is SevenZipLib\SevelZipLib\SevenZipArchive.cs:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern SafeLibraryHandle LoadLibrary(
[MarshalAs(UnmanagedType.LPTStr)] string lpFileName);
The project contains numerous P/Invokes into kernel32.dll (LoadLibrary(), GetProcAddress(), FreeLibrary()), ole32.dll (PropVariantClear()), oleaut32.dll (SafeArrayCreateVector()), and more.
In short, this library is intimately tied to Windows, and isn't going to work on a non-Windows platform in any meaningful fashion, not without a lot of work.
If you need 7z support in a Mono for Android application, you'll need to look into a different library. It looks like the 7-zip SDK includes C# source for reading LZMA files that doesn't rely on P/Invoke, so perhaps that would work?