ETH Basic to Advance Smart Contract Hacking for web3 in 2023 | by Dr. Gupta | Feb, 2023 | Medium | Medium

 

ETH Advance Smart Contract Hacking for web3 in 2023

Basic to know about Smart Contracts :

web3doctor.medium.com

Basic to know about Smart Contracts :

Smart Contract defines as “a set of promises, specified in digital form, including protocols within which the parties perform on the other promises.”

In terms of Ethereum: “smart contracts” to refer to immutable computer programs that run deterministically in the context of an Ethereum Virtual Machine as part of the Ethereum network protocol — i.e., on the decentralized Ethereum world computer.

  • contracts only run if they are called by a transaction. All smart contracts in Ethereum are executed, ultimately, because of a transaction initiated from an EOA.
  • A transaction to a contract address destination will execute the contract in EVM and will call the function named in the data payload of your transaction, if there is no data in your transaction then EVM will call a fallback function and if that function is payable, will execute it to determine what to do next. if no fallback function or non-payable fallback function, transaction will be reverted.
  • A function selector : The first 4 bytes of the Keccak-256 hash of the function’s prototype. This allows the contract to unambiguously identify which function you wish to invoke.

The function arguments

The function’s arguments, encoded according to the rules for the various elementary types defined in the ABI specification.

  • In DollarFactory smart contract example, we defined a function for withdrawals: function withdraw(uint _amount) public {}
  • The prototype of a function is defined as the string containing the name of function, followed by data types of each of its arguments, enclosed in parentheses as separated by commas. The function name here is withdraw and it takes a single argument what is a uint (which is an alias for uint256), so the prototype of withdraw would be: withdraw(uint)256
  • To calculate the Keccak-256 hash of this string in parity;
web3.utils.sha3("withdraw(uint256)");

Multisignature Transfer:

  • transfer ether to a multisig contract
  • want to send funds to another account
  • all the required users will need to send transactions to contract using a regular wallet app, authorizing contract to perform final transaction.

Ethereum HIgh-Level Languages:

Solidity

soliditylang.org

A procedural (imperative) programming language with a syntax similar to JavaScript, C++, or Java. The most popular and frequently used language for Ethereum smart contracts.

Vyper

A more recently developed language, similar to Serpent and again with Python-like syntax. Intended to get closer to a pure-functional Python-like language than Serpent, but not to replace Serpent.

Bamboo

A newly developed language, influenced by Erlang, with explicit state transitions and without iterative flows (loops). Intended to reduce side effects and increase auditability. Very new and yet to be widely adopted.

Others:

LLL, Serpent

Building Smart Contract with Solidity

Official Solidity Documentation website : CLICK HERE

  • Solidity compiler, solc, which converts programs written in the Solidity language to EVM bytecode. The project also manages the important application binary interface (ABI) standard for Ethereum smart contracts
  • https://docs.soliditylang.org/en/latest/installing-solidity.html
  • To install Solidity solc, we will add using Linux Packages: Solidity have PPAs for Ubuntu, use below commands to install:
sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install solc

//you can also install solidity using npm:
npm install -g solc

To check it has installed properly or not, check version;

solc --version

Compiling with the Solidity Compiler (solc)

We use the — bin and — optimize arguments of solc to produce an optimized binary of our example contract developed in my previous article of this series. Learn Ethereum smart contract basics for web3 development 2023 https://medium.com/@web3doctor/learn-ethereum-smart-contract-basics-for-web3-2023-611dcc1caff9

solc --optimize --bin DollarFactory.sol

The Ethereum Contract ABI:

ABI = application binary interface ; defines how data structures and functions are encoded and decoded into OR out of machine code

Purpose of ABI: define functions, describe how function will accept arguments and return result.

It will be helpful when you try to solve, Ethernaut CTFs first part.

To interact with deployed contract, an application needs ; an ABI and address of contract.

solc --abi DollarFactory.sol

Data Types in Solidity Programming:

  • Boolean (bool) : true or false, with logical operators; ! (not), && (and), || (or), == (equal), ≠ (not equal).
  • Integer ( int, uint) : signed (int), unsigned (uint), declared in steps of 8 bits of increments from int8 to uint256, without size suffix, 256-bit are used
  • Fixed point (fixed, ufixed) : fixed / ufixed ; Signed and unsigned fixed point number of various sizes. Keywords ufixedMxN and fixedMxN, where Mrepresents the number of bits taken by the type and Nrepresents how many decimal points are available. Its a fancy way of floating point in solidity. Fixed point numbers are not fully supported by solidiy as per version 0.8.18. They can be declared but cannot be assigned to or from.
  • Address (address payable, address) : address payable is an address you can send Ether to with additional members transfer, balance and send, while you are not supposed to send Ether to a plain address as it might be a smart contract.
  • Fixed-size byte arrays : The value types bytes1, bytes2, bytes3, …, bytes32hold a sequence of bytes from one to up to 32.
  • dynamically-sized byte array : can be bytes or string dynamically assigned
  • Enums : user-defined type, convertible to and from all integer types, require at least one member, cannot have more than 256 member; enum NAME { LABEL1, LABEL2, …}
  • Function Types: internal and external functions, internal functions only inside current contract, external functions consist of address and function signature, can be passed via and returned from external function calls function (<parameter types>) {internal|external} [pure|view|payable] [returns (<return types>)]
  • Data Location: memory, storage, calldata
  • Structs : use to define new types in the form of structs
  • Ether Units : wei, gwei, ether ; finnery and szabo removed in version 0.7.0
  • Time Units : seconds, minutes, hours, days, weeks ; years removed in version 0.5.0, cannot be applied to variables

Control Structures:

  • if, else, while, do, for, break, continue, return
  • Error handling : Assert, Require, Revert, Exceptions

Constructor is executed as a part of contract creation only once then it is discarded.

Selfdestruct : it should not be in a contract code as it can be used to delete contract and withdraw all money

Function Modifiers: special function, use to create conditions that apply to many functions within a contract

contract inheritance: extend base contract with additional functionality, inherits all the methods, functions, and variable of parent, support multiple inheritance by comma separated contract names ; contract child is Parent1, Parent2 {}

Events: completed transaction produce a receipt, contains log enteries, provide information about action occurred during the execution of transaction.

event Withdrawal(address indexed to, uint amount);
event Deposit(address indexed from, uint amount);

emit: incorporate the event data in the transaction logs

function withdraw(uint _amount) public {
msg.sender.transfer(_amount);
emit withdraw(msg.sender, _amount);
}
receive () external payable {
	emit Deposit(msg.sender, msg.value);
}

Gas Considerations:

  • avoid dynamically sized arrays
  • avoid calling other contract without knowing gas cost of their functions,
  • avoid using library not well tested and broadly used

Now you have understood the very basics of Solidity Programming, use above learned points to understand below security and hack leading codes.

Security Considerations:

While it is usually quite easy to build software that works as expected, it is much harder to check that nobody can use it in a way that was not anticipated.

all smart contracts are public, and any user can interact with them simply by creating a transaction, Any vulnerability can be exploited, and losses are almost always impossible to recover.

Security Best Practices

  • Minimalism / simplicity : the simpler the code, the lower the chances are of a bug.
  • code reuse : Try not to reinvent the wheel, don’t repeat yourself
  • code quality : once launched, there’s little to fix any problem
  • Readablility / auditability : the easier it is to read, the easier it is to audit.
  • Test Coverage : test everything that you can

Smart Contract Security Risk and Antipatterns: Be familiar with most common security risks

Reentrancy :

Arithmetic Over / Underflows :

Unexpected Ether :

Delegatecall

call delegatecall useful to modularize the code, call is run in context of external contract/function, delegatecall executed at the targeted address is run in context of calling contract and msg.sender and msg.value remain unchanged.

Default Visibilities:

Entropy Illusion :

External contract Referencing :

Short address / parameter attack :

Unchecked CALL Return Values :

Race Conditions / Front Running :

Denial of Service (DOS) :

  • Looping through externally manipulated mappings or arrays : contracts should not loop through data structures that can be artificially manipulated by external users
  • Owner operations : a privileged user was required to change the state of the contract. In such examples a failsafe can be used in the event that the owner becomes incapacitated, make the owner a multisig contract, use a time-lock,
  • Progressing state based on external calls
  • GovernMental 1100 ether after 2.5M gas : https://www.reddit.com/r/ethereum/comments/4ghzhv/governmentals_1100_eth_jackpot_payout_is_stuck/

Block Timestamp Manipulation :

Constructors with care :

Uninitialized storage pointers :

Tx.origin authetication :

  • travel the entire call stack, contain the address of the account that originally sent the call or transaction and use it for authentication.
  • vulnerable to phising attack
  • prevention : shouldn’t use for authorization, can be use to prevent intermediate contracts to call and only limit contract to regular codeless addresses

“Mastering Ethereum by Andreas M. Antonopoulos and Dr. Gavin Wood (O’Reilly). Copyright 2019 The Ethereum Book LLC and Gavin Wood, 978–1–491–97194–9.”

Follow me on Twitter: https://twitter.com/BgxDoc

'블록체인' 카테고리의 다른 글

HackerOne and the OWASP Top 10 for LLM: A Powerful Alliance for Secure AI  (0) 2024.04.15
HamsterWheel SUI  (0) 2023.06.21
블로그 이미지

wtdsoul

,

DJI Configs Files

드론 2023. 5. 8. 02:32

https://wiki.dji-rev.com/howto/dji_configs

 

howto:dji_configs [dji.retroroms.info]

DJI Configs Files NOTE: The dji_configs files do not work on the most recent DJI GO software versions, you must be on 4.1.12 or older. This information is here for archival purposes only unless you wish to perform an IPA Rollback Click Here For More Detail

wiki.dji-rev.com

DJI Configs Files

NOTE: The dji_configs files do not work on the most recent DJI GO software versions, you must be on 4.1.12 or older. This information is here for archival purposes only unless you wish to perform an IPA Rollback Click Here For More Details or are sideloading an older app onto your Android device

The DJI Configs file mod will work on both Android and iOS. The maximum power at which consumer products can transmit on the 2.4Ghz wifi frequency used by DJI aircraft is 0.1 watts (0.1W) in many countries. In a minority of countries, including the U.S. it is 1W. Some countries lie in between. Only one country, India, allows more than 1W (In India, the max is 4W!). In most parts of the world DJI aircraft uses a power output of 0.1W by default, which is pretty weak. In the U.S., it uses 0.4W. However, the equipment can be configured to a maximum of 1.5 Watts of TX power anywhere in the world with the directions below.

Warnings

  • Changing the video frequency to 2.33 or 2.57 ghz will be using the ISM/LIPD band. Transmitting below 0.1W is permitted in most countries without a license. Transmitting on these frequencies at higher power require the operator to hold a HAM radio license in most countries. Make sure you check your local laws before applying these changes.
  • Transmitting at higher power levels than the 0.5W is not approved by DJI. Do not use this power level unless you understand the risks of transmitting at this power level.

Supported Versions

There have been many questions about supported software/firmware on an aircraft, remote control, and even DJI go itself. This part of this page will attempt to answer some of those questions.

Firstly, lets look at how this all works:

  1. DJI GO parses, and sends commands to an RC based on an config file
  2. The RC receives the messages from DJI go, and updates its own radio settings, and passes the commands to the AC
  3. The AC receives the messages from the RC, and reconfigures its radio settings.

32 Channel Mod file

This file adds additional channels within the 2.4 ghz band increasing them to 32. Depending on the GO App, by selecting “manual channel selection” one of the additional channels can be set. This can be useful in certain circumstances for example when flying multiple dji craft in the same proximity. Or in a dense interference area. Currently, the 32 Ch. mod cannot be combined with the FCC mods.

Manual Apply the config (Android)

  • Download your config file from one of the options below
  • Rename the file to .DJI.configs (note the preceding “.”)
  • Kill the DJI GO 4 app on your android device
  • Connect your device to your PC
  • Copy the .DJI.configs file to this folder on your device: \Android\data\dji.go.v4\files
  • done

Auto Apply the config (Android) with App

Is FCC mod working? How to check?

To make some clarity about the FCC argument and to verify if it is working, as the wide confusion surrounding the subject, I wanted to tell you that the FCC mod using the .DJI.configs (take care: put the dot DJI dot configs file in the right folder \Android\data\dji.go.v4\files) works, it doesn't matter of the number of WIFI CHANNELS shown by the application. In a nutshell, to avoid misunderstanding, FILE insertion will enable FCC mode even if you are in a non-FCC area. You will not see anything about your application that warns you whether it is active or not. It works just fine. The only way to test the FCC mode is to measure transmit power with a dedicated tool, or, as I did, fly two drones, mavic in my case, in the same place at the same time and in the same configurations, with the only difference in the presence of the .DJI.configs file in one of the two drones. Well, one mavic at a distance of about 3800 meters had WEAK SIGNAL and activated the automatic RTH, the other, continued to fly and at a distance of about 4500 meters it had 4 receive notches on the total of 5 in both the controller and in HD. (test stopped because no need to go further)

Here the REAL test showing that .DJI.configs is really working (thanks to @GabrieleFK14 for hardware testing)

CE MODE https://postimg.org/image/3y11dge9f/

FCC 1.5w BOOST MODE (TAKE CARE)

https://s13.postimg.org/3l9n7blpz/FCC_Boost_Mode_1.5w.jpg

how it has tested https://drive.google.com/open?id=1YW47GcpA3hDWGiqj6x2mIJWWKR_XpbtD

(By Lukappaseidue)

EDIT 06/28/2018: There is a trick to know if you are in FCC or CE Mode. I found this on the forum MavicPilots ( https://mavicpilots.com/threads/how-to-know-if-you-are-in-fcc-or-ec-mode.38479/ ). A big thank to DragonJah.

In transmission setting, if you look at the signal graph, you can see than there is two horizontal lines, one for the “~1km” and one for the “~4km”.

If you are in EC mode, the “~1km” line is just under 90 dbm/mhz, so between 90 and 100dbm/mhz and the “~4km” line is between 100 and 110 dbm/mhz.

If you are in FCC mode, the “~1km” line is between 80 and 90 dbm/mhz and the “~4km” line is juste upper 100 dbm/mhz, so between 90 and 100dbm/mhz.

I tried with the 1.5W file but the graph stay like if I was in the EC Mode…

Apply the config (iOS)

This hack is really simple. You only need itunes on your computer. However, there is one more step required for OSX to enable displaying of hidden files in finder before you can start

  • OSX - Display hidden files
  defaults write com.apple.finder AppleShowAllFiles -bool YES
  killAll Finder
  • Download your config file from one of the options below
  • Rename the file to .DJI.configs (note the preceding “.”)
  • Kill the DJI GO 4 app on your apple device
  • Connect your iPhone/iPad/iPod to your PC and open itunes
  • In iTunes, click your apple device, go to apps, scroll to the bottom and find DJI GO 4
  • Add the file in itunes to DJI GO 4 and click Sync/Apply

Note: For OSX users. After dragging the file into iTunes, you will not see it there. iTunes is still hiding the file from you even though it has copied to that folder successfully. If you want to check… or even to upload the file without iTunes, check out http://www.i-funbox.com/

Files

I added a new column that describes where these configurations have been confirmed to be working as expected. The effect of these files in other devices is unknown.

Power or DescriptionVideo FrequencyFileTested On
Default - 0.09W 2.4-2.475ghz dji.configs_force_ce Mavic
Default - 0.09W 2.33ghz dji.configs_force_ce_23 Mavic
Default - 0.09W 2.57ghz dji.configs_force_ce_25 Mavic
FCC - 0.4W 2.4-2.475ghz dji.configs_force_fcc Mavic
FCC - 0.4W 2.33ghz dji.configs_force_fcc_and_23 Mavic
FCC - 0.4W 2.57ghz dji.configs_force_fcc_and_25 Mavic
1.5W 2.4-2.475ghz dji.configs_force_boost Mavic
1.5W 2.33ghz dji.configs_force_boost_and_23 Mavic
1.5W 2.57ghz dji.configs_force_boost_and_25 Mavic
32 Channel Mod   dji.configs_32-ch_mod P3P, P3A, P4P
FCC+ChannelMod   dji.configs_force_fcc_32-ch_mod Experimental

Spectrum Analyzer Observations

Extensive testing of the mod's with a spectrum analyzer in this video by beanbubba. You can find more of his testing at https://mavicpilots.com/threads/mavic-radio-mods-primer.34444/

Detailed Video Tutorial

This tutorial was created by digdat0. He has many tutorials on his website

Hex Dumps

Below, we can see the data contained in each of these files. It is easy to see the individual bits that change for power and frequency tweaks. What is not so obvious at the moment is what part of this file does the 32 channel mod. If anyone has that detail, it would be useful information.

dji.configs_32-ch_mod

00000000  44 4a 49 20 53 4f 46 54  57 41 52 45 20 43 4f 4e  |DJI SOFTWARE CON|
00000010  46 49 47 20 3a 20 44 4f  20 4e 4f 54 20 44 45 4c  |FIG : DO NOT DEL|
00000020  45 54 45 21 00 00 00 01  11 11 11 11 11 11 11 11  |ETE!............|
00000030

dji.configs_force_boost

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 22  |..............."|
00000030  22 22 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |""..............|
00000040  00 00 00 00 00 00 00                              |.......|

dji.configs_force_boost_and_23

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 66  |...............f|
00000030  66 66 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |ff..............|
00000040  00 00 00 00 00 00 00                              |.......|

dji.configs_force_boost_and_25

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 aa  |...............?|
00000030  aa aa 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |??..............|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_ce

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 44  |...............D|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_ce_23

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 44  |...............D|
00000030  44 44 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |DD..............|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_ce_25

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 88  |................|
00000030  88 88 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_fcc

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 11  |................|
00000030  11 11 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_fcc_and_23

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 55  |...............U|
00000030  55 55 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |UU..............|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

dji.configs_force_fcc_and_25

00000000  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000010  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
00000020  01 01 01 01 01 01 01 01  00 00 00 00 00 00 00 99  |................|
00000030  99 99 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00                              |.......|
00000047

Credits

Code

The code below was reverse engineered from DJI GO 4.1.12. It is included here to help people see that even the latest DJI GO app still parses this file.

DJIAppSettings-loadDJICfg.c
void __cdecl -[DJIAppSettings loadDJICfg](DJIAppSettings *self, SEL a2)
{
  DJIAppSettings *v2; // x19
  struct objc_object *v3; // x0
  void *v4; // x0
  void *v5; // x21
  void *v6; // x0
  __int64 v7; // x20
  void *v8; // x0
  void *v9; // x0
  void *v10; // x21
  void *v11; // x0
  void *v12; // x0
  void *v13; // x0
  __int64 v14; // x8
  void *v15; // x0
  void *v16; // x0
  void *v17; // x0
  char v18; // w22
 
  v2 = self;
  v3 = +[DJIFileHelper fetchDocumentPath](&OBJC_CLASS___DJIFileHelper, "fetchDocumentPath");
  v4 = (void *)objc_retainAutoreleasedReturnValue(v3);
  v5 = v4;
  v6 = objc_msgSend(v4, "stringByAppendingPathComponent:", CFSTR(".DJI.configs"));
  v7 = objc_retainAutoreleasedReturnValue(v6);
  objc_release(v5);
  v8 = objc_msgSend(&OBJC_CLASS___NSData, "dataWithContentsOfFile:", v7);
  v9 = (void *)objc_retainAutoreleasedReturnValue(v8);
  v10 = v9;
  if ( v9 )
  {
    v2->_canUseIllegalChannels = 0;
    v2->_mfiDisable = 0;
    v2->_firmwareServiceType = 0;
    v2->_limitCameraRecordingTime = 1;
    v2->_simulatorInternalDisable = 0;
    if ( (unsigned __int64)objc_msgSend(v9, "length") >= 0x29 )
    {
      v11 = (void *)objc_retainAutorelease(v10);
      if ( *((_BYTE *)objc_msgSend(v11, "bytes") + 39) == 1 )
        v2->_canUseIllegalChannels = 1;
    }
    if ( (unsigned __int64)objc_msgSend(v10, "length") >= 0x2A )
    {
      v12 = (void *)objc_retainAutorelease(v10);
      if ( *((_BYTE *)objc_msgSend(v12, "bytes") + 40) == 1 )
        v2->_mfiDisable = 1;
    }
    if ( (unsigned __int64)objc_msgSend(v10, "length") >= 0x2D )
    {
      v13 = (void *)objc_retainAutorelease(v10);
      v14 = *((unsigned __int8 *)objc_msgSend(v13, "bytes") + 43);
      if ( (_DWORD)v14 == 2 )
        v2->_firmwareServiceType = 2;
      else
        v2->_firmwareServiceType = v14 == 1;
    }
    if ( (unsigned __int64)objc_msgSend(v10, "length") >= 0x2E )
    {
      v15 = (void *)objc_retainAutorelease(v10);
      if ( *((_BYTE *)objc_msgSend(v15, "bytes") + 44) == 1 )
        v2->_limitCameraRecordingTime = 0;
    }
    if ( (unsigned __int64)objc_msgSend(v10, "length") >= 0x2F )
    {
      v16 = (void *)objc_retainAutorelease(v10);
      if ( *((_BYTE *)objc_msgSend(v16, "bytes") + 45) == 1 )
        v2->_simulatorInternalDisable = 1;
    }
    if ( (unsigned __int64)objc_msgSend(v10, "length") >= 0x31 )
    {
      v17 = (void *)objc_retainAutorelease(v10);
      v18 = *((_BYTE *)objc_msgSend(v17, "bytes") + 48);
      if ( v18 & 1 )
        -[DJIAppSettings setSdr_force_fcc:](v2, "setSdr_force_fcc:", 1LL);
      if ( v18 & 2 )
        -[DJIAppSettings setSdr_force_boost:](v2, "setSdr_force_boost:", 1LL);
      if ( v18 & 4 )
        -[DJIAppSettings setSdr_force_2_3_G:](v2, "setSdr_force_2_3_G:", 1LL);
      if ( v18 & 8 )
        -[DJIAppSettings setSdr_force_2_5_G:](v2, "setSdr_force_2_5_G:", 1LL);
    }
  }
  objc_release(v10);
  objc_release(v7);
}
블로그 이미지

wtdsoul

,

https://bakjuna.tistory.com/135?category=816799 

 

[solana] 솔라나 스마트 컨트랙트 만들어보기

수정: 실제로 현업에서 작동하는 프로그램을 제작하시려면 https://bakjuna.tistory.com/143 여길 참조해주세요! 이 글에선 솔라나 네이티브 코드로 제작하는 법을 설명하고 있습니다. 1. 들어가며 솔라

bakjuna.tistory.com

 

수정: 실제로 현업에서 작동하는 프로그램을 제작하시려면 https://bakjuna.tistory.com/143 여길 참조해주세요! 이 글에선 솔라나 네이티브 코드로 제작하는 법을 설명하고 있습니다.

1. 들어가며

솔라나는 최근 아주 각광받는 레이어1 코인입니다. 일단 gas fee가 이더리움에 비해 압도적으로 저렴하고, PoH라는 새로운 접근 방식을 통해 초당 트랜잭션 수도 아주 뛰어나 무려 초당 5만 개에 달하는 트랜잭션을 처리할 수 있습니다. 기존 비트코인, 이더리움의 초당 10여 개에 불과한 트랜잭션 수와 비교하면 아주 장족의 발전이죠.

 

트랜잭션의 gas fee도 현재 5000Lamport (0.000000001SOL) 에 불과해 20만원이 1솔라나라고 가정하면 트랜잭션당 소모되는 gas fee가 10원에 불과합니다. 해외 송금 해보신 분들은 아실거에요. 이 수치가 얼마나 대단한 것인지... 순식간에 이체되고, 아주 적은 비용으로 송금이 가능합니다.

 

솔라나는 당연히 최신 기술인 NFT 민팅과 Smart Contract, Defi 등을 지원합니다. 이번 글에선, 이 모든 기술들의 근간이 될 스마트 컨트랙트를 빌딩하는 방법에 대해서 알아보려고 합니다.

 

2. 스마트 컨트랙트란?

사실 많은 분들이 스마트 컨트랙트가 뭔지 구체적으로 알지 못하고 계시지만, 개념은 엄청 간단합니다. 그냥 자판기를 생각하시면 됩니다. 내가 어떤 일을 하면 어떤 결과가 나올지 미리 정해진 스크립트에 따라 수행되는 것이죠! 인터넷에 수행될 코드를 미리 업로드시켜놓고, 수행 조건이 만족되면 해당 코드가 자동으로 실행되고 연산됩니다. 이게 답니다!

 

그럼 이게 왜 혁신적이냐고요? 왜냐면, 기존에는 다들 '신뢰'에 기초해서 하던 작업들을 이젠 딱히 상대를 신뢰하지 않아도 되거든요. 예를 들면 제가 어떤 게임을 하고 이겼을 때 1000원을 받는다고 해봅시다. 종전에는 이 게임을 하고 1000원을 받는 행위 자체를 해당 사이트를 '신뢰'하지 않으면 할 수 없었습니다. 게임 사이트가 나에게 돈을 줄지, 주지 않을지 어떻게 아나요?

 

하지만 블록체인 스마트 컨트랙트는 다릅니다. 스마트 컨트랙트 온체인에서 일어나는 모든 일들은 스크립트를 읽을 수 있는 능력만 있다면 게임사이트가 특정 조건을 만족하면 자동으로 나에게 돈을 준다는 사실을 알 수 있습니다. 그렇지 않다면, 교묘하게 그렇지 않은 코드를 삽입했다는 사실도 알아낼 수 있죠. 현재는 일부 프로그래머만이 해당 사실을 검증할 수 있겠습니다만, 적어도 모두에게 공개되어있는 코드에 대놓고 스캠 코드를 삽입할 수는 없겠죠?

 

스마트 컨트랙트에 대한 대략적인 설명입니다. 먼저 프로그램된 컨트랙트 (계약)을 올려놓고, 이벤트가 진행이 되면 해당 이벤트가 실행이 됩니다. 그 실행 내역에 따라서 토큰 (뭐... 돈이죠) 이 오가는 것을 보증할 수 있습니다.

 

3. 스마트 컨트랙트 예제 살펴보기

3.1) 설치

 

솔라나 스마트 컨트랙트 예제를 살펴봅시다. 솔라나는 스마트 컨트랙트는 러스트로 짜여져 있고, 소통은 node로 할 수 있습니다.

 

 

  git clone git@github.com:solana-labs/example-helloworld.git
  sh -c "$(curl -sSfL https://release.solana.com/v1.9.1/install)"

 

이 프로젝트를 받아봅시다. 솔라나의 예제 프로젝트에요. 그리고, 솔라나도 한번 깔아봅시다. 두 번째 줄이 솔라나 CLI를 설치하는 구문입니다.

 

설치하고 나서 한번 살펴볼까요?

 

 

  solana config set --url https://api.devnet.solana.com

 

솔라나 데브넷으로 설정해보면, 다음과 같은 설정 완료창이 뜨는 것을 알 수 있습니다.

 

 

solana config 파일 저장 위치와, keypair 위치가 뜹니다. 제 솔라나 월렛 키페어가 만들어져있기 때문에 뜨는 것이죠. 만약 keypair가 뜨지 않는다면, 생성해주셔야 합니다.

 

 

 

  solana-keygen new

 

솔라나 키를 이 명령어로 생성해줄 수 있습니다.

 

3.2) 스마트 컨트랙트

솔라나는 러스트를 스마트 컨트랙트 언어로 사용한다고 했습니다. 러스트 기본 언어 문법은 배워두는게 좋습니다. 모른다고 하더라도 잠시 작성할 수는 있겠지만, 어쨌든 기초적인 것들은 알아두는게 좋으니까요.

 

solana-helloworld 프로젝트를 살펴보시면 program-rust/src/lib.rs 파일이 존재합니다. 이게 러스트 파일인데요, 이 파일이 컴파일되면 솔라나 스마트 컨트랙트가 됩니다. 한번 해당 파일을 살펴봅시다.

 

 

 

  use borsh::{BorshDeserialize, BorshSerialize};
  use solana_program::{
  account_info::{next_account_info, AccountInfo},
  entrypoint,
  entrypoint::ProgramResult,
  msg,
  program_error::ProgramError,
  pubkey::Pubkey,
  };
   
  /// Define the type of state stored in accounts
  #[derive(BorshSerialize, BorshDeserialize, Debug)]
  pub struct GreetingAccount {
  /// number of greetings
  pub counter: u32,
  }
   
  // Declare and export the program's entrypoint
  entrypoint!(process_instruction);
   
  // Program entrypoint's implementation
  pub fn process_instruction(
  program_id: &Pubkey, // Public key of the account the hello world program was loaded into
  accounts: &[AccountInfo], // The account to say hello to
  instruction_data: &[u8], // Ignored, all helloworld instructions are hellos
  ) -> ProgramResult {
  msg!("Hello World Rust program entrypoint");
   
  // Iterating accounts is safer then indexing
  let accounts_iter = &mut accounts.iter();
   
  // Get the account to say hello to
  let account = next_account_info(accounts_iter)?;
   
  // The account must be owned by the program in order to modify its data
  if account.owner != program_id {
  msg!("Greeted account does not have the correct program id");
  return Err(ProgramError::IncorrectProgramId);
  }
   
  // Increment and store the number of times the account has been greeted
  let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?;
  let num: u32 = instruction_data[0] as u32;
  greeting_account.counter += num;
  greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;
   
  msg!("Greeted {} time(s)!", greeting_account.counter);
   
  Ok(())
  }
   
  // Sanity tests
  #[cfg(test)]
  mod test {
  use super::*;
  use solana_program::clock::Epoch;
  use std::mem;
   
  #[test]
  fn test_sanity() {
  let program_id = Pubkey::default();
  let key = Pubkey::default();
  let mut lamports = 0;
  let mut data = vec![0; mem::size_of::<u32>()];
  let owner = Pubkey::default();
  let account = AccountInfo::new(
  &key,
  false,
  true,
  &mut lamports,
  &mut data,
  &owner,
  false,
  Epoch::default(),
  );
  let instruction_data: Vec<u8> = Vec::new();
   
  let accounts = vec![account];
   
  assert_eq!(
  GreetingAccount::try_from_slice(&accounts[0].data.borrow())
  .unwrap()
  .counter,
  0
  );
  process_instruction(&program_id, &accounts, &instruction_data).unwrap();
  assert_eq!(
  GreetingAccount::try_from_slice(&accounts[0].data.borrow())
  .unwrap()
  .counter,
  1
  );
  process_instruction(&program_id, &accounts, &instruction_data).unwrap();
  assert_eq!(
  GreetingAccount::try_from_slice(&accounts[0].data.borrow())
  .unwrap()
  .counter,
  2
  );
  }
  }
view rawlib.rs hosted with ❤ by GitHub

 

조금 긴데 사실 간단합니다. 지금 단계에서 알아야 할 내용은 얼마 없거든요.

 

borsh는 Binary Object Representation Serializer for Hashing 의 약어입니다. 바이너리로 풀어진 오브젝트를 시리얼라이징하거나 디시리얼라이징할 때 쓰이는 일종의 라이브러리라고 생각하시면 됩니다. node에도 동일하게 존재하는 라이브러리입니다.

 

entrypoint!() 에서 실제 스마트 컨트랙트가 선언되는데, 이 안 내용을 한번 살펴보시죠.

 

account.iter()는 map과 비슷한겁니다. account를 iterable하게 돌려서 account를 하나씩 살펴본다는 의미입니다. 그래서 next_account_info로 account를 가지고 온 후, 해당 account_info에 데이터를 set해줄 준비를 할 겁니다. 데이터를 저장해야 그 데이터로 무언가 로직을 돌릴테니, 이번 예제에선 데이터를 저장하는 로직만 해볼거에요. 그러니까... UPDATE, INSERT, SELECT 세 기능을 구현해 볼 겁니다.

 

 

  let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?;
  let num: u32 = instruction_data[0] as u32;
  greeting_account.counter += num;
  greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;
   
  msg!("Greeted {} time(s)!", greeting_account.counter);
   
  Ok(())

 

여기가 핵심 로직인데요, account의 data를 가지고 와서, instruction_data를 해당 data에 set 해주는 부분입니다. instruction_data는 우리가 직접 넣어주는 데이터가 될 거에요. 그 다음 다시 저장해주고 Ok() 해주면, 해당 노드 블럭에 스마트 컨트랙트 내용이 저장됩니다.

 

여기까지 간단하게 러스트 코드를 살펴봤습니다. 너무 간단해서 볼 내용도 별로 없죠?

 

3.3) 데이터 set 하고 불러오기

부차적인 내용은 다 빼고, 하나하나 차근차근 빠르게 보겠습니다.

 

1] 커넥션 맺기

 

  const rpcUrl = await getRpcUrl();
  connection = new Connection(rpcUrl, 'confirmed');
  const version = await connection.getVersion();
  console.log('Connection to cluster established:', rpcUrl, version);

 

rpcUrl은 devNet 주소입니다. jsonRPC로 통신할 url이 어딘지 fetch해오거나 아니면 선언해주는 곳입니다. 그 이후, confirmed 블록만 가져와서 커넥션을 맺어주는걸 new Connection을 통해 진행합니다.

 

 

 

  let fees = 0;
  if (!payer) {
  const {feeCalculator} = await connection.getRecentBlockhash();
   
  // Calculate the cost to fund the greeter account
  fees += await connection.getMinimumBalanceForRentExemption(GREETING_SIZE);
   
  // Calculate the cost of sending transactions
  fees += feeCalculator.lamportsPerSignature * 100; // wag
   
  payer = await getPayer();
  }
   
  let lamports = await connection.getBalance(payer.publicKey);
  if (lamports < fees) {
  // If current balance is not enough to pay for fees, request an airdrop
  const sig = await connection.requestAirdrop(
  payer.publicKey,
  fees - lamports,
  );
  await connection.confirmTransaction(sig);
  lamports = await connection.getBalance(payer.publicKey);
  }
   
  console.log(
  'Using account',
  payer.publicKey.toBase58(),
  'containing',
  lamports / LAMPORTS_PER_SOL,
  'SOL to pay for fees',
  );
view rawgetPayer.ts hosted with ❤ by GitHub

 

payer를 정해줍니다. 이번엔 devnet이기 때문에, payer는 우리죠. 따라서 만약 부족하면 데브넷에서 에어드롭을 받는 로직까지 추가합니다. 실제 디앱에선 이렇게 하면 안되고 에어드롭 받는 부분은 제외해야합니다. 만약 잔액이 부족하면 그냥 에러를 뱉어야죠.

 

 

 

  try {
  const programKeypair = await createKeypairFromFile(PROGRAM_KEYPAIR_PATH);
  programId = programKeypair.publicKey;
  } catch (err) {
  const errMsg = (err as Error).message;
  throw new Error(
  `Failed to read program keypair at '${PROGRAM_KEYPAIR_PATH}' due to error: ${errMsg}. Program may need to be deployed with \`solana program deploy dist/program/helloworld.so\``,
  );
  }

 

프로그램 에러가 있는지, 프로그램이 있긴 한지 체크해봅니다.

 

 

 

  const instruction = new TransactionInstruction({
  keys: [{pubkey: greetedPubkey, isSigner: false, isWritable: true}],
  programId,
  data: Buffer.alloc(1, 2), // 실제 넣을 데이터
  });
   
  await sendAndConfirmTransaction(
  connection,
  new Transaction().add(instruction),
  [payer],
  );
view rawtransaction.ts hosted with ❤ by GitHub

 

이제 실제로 트랜잭션을 발생시킵니다. TransactionInstruction의 input이 아까 러스트랑 동일하죠? 맞습니다, 러스트에서 받는 인자들입니다. 따라서 data에 저렇게 넣으면 2라는 숫자가 들어갑니다. 중요한건, Buffer로 선언된 ㄹㅇ 바이너리 숫자가 들어간다는 사실입니다.

 

 

 

  const accountInfo = await connection.getAccountInfo(greetedPubkey);
  if (accountInfo === null) {
  throw 'Error: cannot find the greeted account';
  }
  const greeting = borsh.deserialize(
  GreetingSchema,
  GreetingAccount,
  accountInfo.data,
  );

 

트랜잭션이 맺어지고 난 이후 현재 데이터는 어떻게 불러올까요? getAccountInfo를 통해 가져와서, data를 불러옵니다. 그러면 우리가 set한 데이터 정보들이 나옵니다!

 

 

4. 마무리

이렇게 솔라나로 아주 간단한 스마트 컨트랙트를 만들어 봤습니다. 노드를 통해 통신할 수 있으니, 아마 노드 웹서버를 통해 통신할 수도 있겠지요.

 

이런 스마트 컨트랙트를 openDB, open Logic으로도 사용할 수 있습니다. 누구나 볼 수 있는 DB, 그리고 누구나 볼 수 있는 로직이기 때문에 절대로 속일 수 없다는 특징을 가지게 된 것이죠. 누구나 검증할 수 있게 된 것입니다. 물론, 스마트컨트랙트를 누구나 발생시킬 수 있기 때문에, 실제 구현상에선 greetedPubKey의 SEED를 적절하게 잘 숨겨서 보관하는 것도 중요합니다. 해당 seed가 곧 DB의 암호가 되는 셈이니까요.

 

이 글이 한국어 사용자의 스마트 컨트랙트 이해도 향상에 조금이나마 도움이 되었으면 좋겠습니다! 기회가 된다면 다음 글로 곧 스마트컨트랙트의 실제 활용도 한번 보여드리겠습니다.

 

추가)

사실 프로그램을 만들 때엔 anchor를 이용하시는 것이 좋습니다. 해당 글도 읽어보세요!

https://bakjuna.tistory.com/138

 

[anchor] anchor를 이용하여 solana program (smart contract) 작성하기

1. 들어가며 anchor는 solana 프로그램을 작성할 때 훨씬 더 쉽게 작성할 수 있게 도움을 주는 라이브러리입니다. 솔라나 프로그램을 네이티브로 작성하는 것보다, anchor를 이용하여 작성하는게 훨씬

bakjuna.tistory.com

 

블로그 이미지

wtdsoul

,

https://www.skyer9.pe.kr/wordpress/?p=4518 

 

Ubuntu 20.04 ARM Cross Compile 하기 – 상구리의 기술 블로그

Ubuntu 20.04 ARM Cross Compile 하기 기초지식 ARM 은 hard float(하드웨어 GPU) 가 있는 버전이 있고, 없는 버전이 있습니다. EABI(Embedded Application Binary Interface)는, ARM의 C 호출 관행이라고 이해하면 됩니다. 툴

www.skyer9.pe.kr

 

Ubuntu 20.04 ARM Cross Compile 하기

기초지식

ARM 은 hard float(하드웨어 GPU) 가 있는 버전이 있고,
없는 버전이 있습니다.

EABI(Embedded Application Binary Interface)는,
ARM의 C 호출 관행이라고 이해하면 됩니다.

툴체인 설치

개발용 필수 라이브러리 설치

 sudo apt-get install build-essentialCOPY

hard float(하드웨어 GPU) 가 있는 경우

# gnu c compiler(32bit)
sudo apt-get install gcc-arm-linux-gnueabihf
# gnu c++ compiler(32bit)
sudo apt-get install g++-arm-linux-gnueabihfCOPY

hard float(하드웨어 GPU) 가 없는 경우

# gnu c compiler(32bit)
sudo apt-get install gcc-arm-linux-gnueabi
# gnu c++ compiler(32bit)
sudo apt-get install g++-arm-linux-gnueabiCOPY

64bit 버전

# gnu c compiler
sudo apt-get install gcc-aarch64-linux-gnu
# gnu c++ compiler
sudo apt-get install g++-aarch64-linux-gnuCOPY

컴파일

Hello, World!

vi hello.cpp
--------------------------
#include <iostream>
using namespace std;

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}
--------------------------

arm-linux-gnueabihf-g++ -g -o hello hello.cpp
file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV) ......

aarch64-linux-gnu-g++ -g -o hello hello.cpp
file hello
hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV) ......COPY

make

우선 알아야 할 것은 make 가 직접적으로 cross compile 을 지원하는 것이 아니라,
Makefile 에 cross compile 을 지원하도록 설정해야 하는 것입니다.

들여쓰기는 TAB 문자로만 이루어져야 합니다.
공백문자가 있는 경우 오류가 발생합니다.

AR=${CROSS_COMPILE}ar
AS=${CROSS_COMPILE}as
LD=${CROSS_COMPILE}ld
CC=$(CROSS_COMPILE)gcc
CXX=$(CROSS_COMPILE)g++
NM=${CROSS_COMPILE}nm
RANLIB=${CROSS_COMPILE}ranlib

CFLAGS=""
CPPFLAGS=""
LDFLAGS=""
LIBS=""

hello : hello.cpp
        $(CXX) -g -o hello hello.cpp

clean:
        rm helloCOPY

make 를 이용하여 컴파일하는 경우, 아래와 같이 환경설정을 추가하고 컴파일하면 됩니다.

# 32bit, GPU 없는 경우
export CROSS_COMPILE=arm-linux-gnueabi-
export ARCH=arm
# 32bit, GPU 있는 경우
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
# 64bit
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

make

file hello
hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV) ......COPY

아래 명령을 .bashrc 에 추가해 놓으면 편합니다.

alias armmake='make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- '
alias arm64make='make -j8 ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- 'COPY

cmake

샘플로 json-c 라이브러리를 컴파일합니다.

git clone https://github.com/json-c/json-c.git
cd json-c
mkdir build
cd build
# cmake ..COPY
vi ../toolchain.arm.cmake
-------------------------------
SET(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
SET(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
SET(CMAKE_LINKER ${CROSS_COMPILE}ld)
SET(CMAKE_NM ${CROSS_COMPILE}nm)
SET(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy)
SET(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump)
SET(CMAKE_RANLIB ${CROSS_COMPILE}ranlib)
-------------------------------COPY
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.arm.cmake -DCROSS_COMPILE=aarch64-linux-gnu- ..

make
file libjson-c.so.5.1.0
libjson-c.so.5.1.0: ELF 64-bit LSB shared object, ARM aarch64, version ......COPY

configure

./configure --host=arm-linux-gnueabiCOPY
 
블로그 이미지

wtdsoul

,

https://domdom.tistory.com/596

 

[frida] 프리다 안드로이드 SSL/TLS 피닝 우회 스크립트

지난 글에서는 리패키징을 통한 SSL/TLS 피닝 우회 방법에 대해서 언급했었는데요. 아래 링크에서 참고해보실 수 있습니다. https://domdom.tistory.com/377 [apk-mitm] APK 파일 SSL/TLS pinning 우회 및 기능 없애

domdom.tistory.com

 

 

setImmediate(function(){
Java.perform(function() {
    var array_list = Java.use("java.util.ArrayList");
    var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
    TrustManagerImpl.checkTrustedRecursive.implementation = function(a1, a2, a3, a4, a5, a6) {
        var a = array_list.$new();
        return a;
    }
}, 0);
})

 

다만 요즘 금융권 앱의 경우에는 okhttpv3 이며 여러 클래스에서 pinning 을 하고 있어 다양하게 우회를 해야할 필요가 있습니다. 때문에 이럴 때 사용하기 좋은 코드를 찾았는데 아래와 같습니다. (길이가 좀 깁니다)

/* frida -U -f [APP_ID] -l frida_multiple_unpinning.js --no-pause */

setTimeout(function() {
	Java.perform(function() {
		console.log('');
		console.log('======');
		console.log('[#] Android Bypass for various Certificate Pinning methods [#]');
		console.log('======');


		var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
		var SSLContext = Java.use('javax.net.ssl.SSLContext');
		
		// TrustManager (Android < 7) //
		////////////////////////////////
		var TrustManager = Java.registerClass({
			// Implement a custom TrustManager
			name: 'dev.asd.test.TrustManager',
			implements: [X509TrustManager],
			methods: {
				checkClientTrusted: function(chain, authType) {},
				checkServerTrusted: function(chain, authType) {},
				getAcceptedIssuers: function() {return []; }
			}
		});
		// Prepare the TrustManager array to pass to SSLContext.init()
		var TrustManagers = [TrustManager.$new()];
		// Get a handle on the init() on the SSLContext class
		var SSLContext_init = SSLContext.init.overload(
			'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');
		try {
			// Override the init method, specifying the custom TrustManager
			SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
				console.log('[+] Bypassing Trustmanager (Android < 7) pinner');
				SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
			};
		} catch (err) {
			console.log('[-] TrustManager (Android < 7) pinner not found');
			//console.log(err);
		}



	
		// OkHTTPv3 (quadruple bypass) //
		/////////////////////////////////
		try {
			// Bypass OkHTTPv3 {1}
			var okhttp3_Activity_1 = Java.use('okhttp3.CertificatePinner');    
			okhttp3_Activity_1.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {                              
				console.log('[+] Bypassing OkHTTPv3 {1}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] OkHTTPv3 {1} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass OkHTTPv3 {2}
			// This method of CertificatePinner.check is deprecated but could be found in some old Android apps
			var okhttp3_Activity_2 = Java.use('okhttp3.CertificatePinner');    
			okhttp3_Activity_2.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(a, b) {
				console.log('[+] Bypassing OkHTTPv3 {2}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] OkHTTPv3 {2} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass OkHTTPv3 {3}
			var okhttp3_Activity_3 = Java.use('okhttp3.CertificatePinner');    
			okhttp3_Activity_3.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(a, b) {
				console.log('[+] Bypassing OkHTTPv3 {3}: ' + a);
				return;
			};
		} catch(err) {
			console.log('[-] OkHTTPv3 {3} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass OkHTTPv3 {4}
			var okhttp3_Activity_4 = Java.use('okhttp3.CertificatePinner');    
			//okhttp3_Activity_4['check$okhttp'].implementation = function(a, b) {
			okhttp3_Activity_4.check$okhttp.overload('java.lang.String', 'kotlin.jvm.functions.Function0').implementation = function(a, b) {		
				console.log('[+] Bypassing OkHTTPv3 {4}: ' + a);
				return;
			};
		} catch(err) {
			console.log('[-] OkHTTPv3 {4} pinner not found');
			//console.log(err);
		}

	

	
		// Trustkit (triple bypass) //
		//////////////////////////////
		try {
			// Bypass Trustkit {1}
			var trustkit_Activity_1 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier');
			trustkit_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
				console.log('[+] Bypassing Trustkit {1}: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Trustkit {1} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass Trustkit {2}
			var trustkit_Activity_2 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier');
			trustkit_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
				console.log('[+] Bypassing Trustkit {2}: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Trustkit {2} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass Trustkit {3}
			var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager');
			trustkit_PinningTrustManager.checkServerTrusted.overload('[Ljava.security.cert.X509Certificate;', 'java.lang.String').implementation = function(chain, authType) {
				console.log('[+] Bypassing Trustkit {3}');
				//return;
			};
		} catch (err) {
			console.log('[-] Trustkit {3} pinner not found');
			//console.log(err);
		}
		
	
	
  
		// TrustManagerImpl (Android > 7) //
		////////////////////////////////////
		try {
			// Bypass TrustManagerImpl (Android > 7) {1}
			var array_list = Java.use("java.util.ArrayList");
			var TrustManagerImpl_Activity_1 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
			TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function(certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) {
				console.log('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check: '+ host);
				return array_list.$new();
			};
		} catch (err) {
			console.log('[-] TrustManagerImpl (Android > 7) checkTrustedRecursive check not found');
			//console.log(err);
		}  
		try {
			// Bypass TrustManagerImpl (Android > 7) {2} (probably no more necessary)
			var TrustManagerImpl_Activity_2 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
			TrustManagerImpl_Activity_2.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
				console.log('[+] Bypassing TrustManagerImpl (Android > 7) verifyChain check: ' + host);
				return untrustedChain;
			};   
		} catch (err) {
			console.log('[-] TrustManagerImpl (Android > 7) verifyChain check not found');
			//console.log(err);
		}

  
  
		

		// Appcelerator Titanium PinningTrustManager //
		///////////////////////////////////////////////
		try {
			var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');
			appcelerator_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) {
				console.log('[+] Bypassing Appcelerator PinningTrustManager');
				return;
			};
		} catch (err) {
			console.log('[-] Appcelerator PinningTrustManager pinner not found');
			//console.log(err);
		}




		// Fabric PinningTrustManager //
		////////////////////////////////
		try {
			var fabric_PinningTrustManager = Java.use('io.fabric.sdk.android.services.network.PinningTrustManager');
			fabric_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) {
				console.log('[+] Bypassing Fabric PinningTrustManager');
				return;
			};
		} catch (err) {
			console.log('[-] Fabric PinningTrustManager pinner not found');
			//console.log(err);
		}




		// OpenSSLSocketImpl Conscrypt (double bypass) //
		/////////////////////////////////////////////////
		try {
			var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
			OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, JavaObject, authMethod) {
				console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {1}');
			};
		} catch (err) {
			console.log('[-] OpenSSLSocketImpl Conscrypt {1} pinner not found');
			//console.log(err);        
		}
		try {
			var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
			OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certChain, authMethod) {
				console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {2}');
			};
		} catch (err) {
			console.log('[-] OpenSSLSocketImpl Conscrypt {2} pinner not found');
			//console.log(err);        
		}




		// OpenSSLEngineSocketImpl Conscrypt //
		///////////////////////////////////////
		try {
			var OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl');
			OpenSSLEngineSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function(a, b) {
				console.log('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + b);
			};
		} catch (err) {
			console.log('[-] OpenSSLEngineSocketImpl Conscrypt pinner not found');
			//console.log(err);
		}




		// OpenSSLSocketImpl Apache Harmony //
		//////////////////////////////////////
		try {
			var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl');
			OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function(asn1DerEncodedCertificateChain, authMethod) {
				console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony');
			};
		} catch (err) {
			console.log('[-] OpenSSLSocketImpl Apache Harmony pinner not found');
			//console.log(err);      
		}




		// PhoneGap sslCertificateChecker //
		////////////////////////////////////
		try {
			var phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker');
			phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function(a, b, c) {
				console.log('[+] Bypassing PhoneGap sslCertificateChecker: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] PhoneGap sslCertificateChecker pinner not found');
			//console.log(err);
		}




		// IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) //
		////////////////////////////////////////////////////////////////////
		try {
			// Bypass IBM MobileFirst {1}
			var WLClient_Activity_1 = Java.use('com.worklight.wlclient.api.WLClient');
			WLClient_Activity_1.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function(cert) {
				console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert);
				return;
			};
			} catch (err) {
			console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey {1} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass IBM MobileFirst {2}
			var WLClient_Activity_2 = Java.use('com.worklight.wlclient.api.WLClient');
			WLClient_Activity_2.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function(cert) {
				console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert);
				return;
			};
		} catch (err) {
			console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey {2} pinner not found');
			//console.log(err);
		}




		// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) //
		///////////////////////////////////////////////////////////////////////////////////////////////////////
		try {
			// Bypass IBM WorkLight {1}
			var worklight_Activity_1 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
			worklight_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function(a, b) {
				console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + a);                
				return;
			};
		} catch (err) {
			console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {1} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass IBM WorkLight {2}
			var worklight_Activity_2 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
			worklight_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
				console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {2} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass IBM WorkLight {3}
			var worklight_Activity_3 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
			worklight_Activity_3.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function(a, b) {
				console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {3} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass IBM WorkLight {4}
			var worklight_Activity_4 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
			worklight_Activity_4.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
				console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {4} pinner not found');
			//console.log(err);
		}




		// Conscrypt CertPinManager //
		//////////////////////////////
		try {
			var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager');
			conscrypt_CertPinManager_Activity.checkChainPinning.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
				console.log('[+] Bypassing Conscrypt CertPinManager: ' + a);
				//return;
				return true;
			};
		} catch (err) {
			console.log('[-] Conscrypt CertPinManager pinner not found');
			//console.log(err);
		}
		
		


		// Conscrypt CertPinManager (Legacy) //
		///////////////////////////////////////
		try {
			var legacy_conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager');
			legacy_conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
				console.log('[+] Bypassing Conscrypt CertPinManager (Legacy): ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Conscrypt CertPinManager (Legacy) pinner not found');
			//console.log(err);
		}

			   


		// CWAC-Netsecurity (unofficial back-port pinner for Android<4.2) CertPinManager //
		///////////////////////////////////////////////////////////////////////////////////
		try {
			var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager');
			cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
				console.log('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] CWAC-Netsecurity CertPinManager pinner not found');
			//console.log(err);
		}




		// Worklight Androidgap WLCertificatePinningPlugin //
		/////////////////////////////////////////////////////
		try {
			var androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin');
			androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function(a, b, c) {
				console.log('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Worklight Androidgap WLCertificatePinningPlugin pinner not found');
			//console.log(err);
		}




		// Netty FingerprintTrustManagerFactory //
		//////////////////////////////////////////
		try {
			var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory');
			//NOTE: sometimes this below implementation could be useful 
			//var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory');
			netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function(type, chain) {
				console.log('[+] Bypassing Netty FingerprintTrustManagerFactory');
			};
		} catch (err) {
			console.log('[-] Netty FingerprintTrustManagerFactory pinner not found');
			//console.log(err);
		}




		// Squareup CertificatePinner [OkHTTP<v3] (double bypass) //
		////////////////////////////////////////////////////////////
		try {
			// Bypass Squareup CertificatePinner  {1}
			var Squareup_CertificatePinner_Activity_1 = Java.use('com.squareup.okhttp.CertificatePinner');
			Squareup_CertificatePinner_Activity_1.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(a, b) {
				console.log('[+] Bypassing Squareup CertificatePinner {1}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] Squareup CertificatePinner {1} pinner not found');
			//console.log(err);
		}
		try {
			// Bypass Squareup CertificatePinner {2}
			var Squareup_CertificatePinner_Activity_2 = Java.use('com.squareup.okhttp.CertificatePinner');
			Squareup_CertificatePinner_Activity_2.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
				console.log('[+] Bypassing Squareup CertificatePinner {2}: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] Squareup CertificatePinner {2} pinner not found');
			//console.log(err);
		}




		// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) //
		/////////////////////////////////////////////////////////////
		try {
			// Bypass Squareup OkHostnameVerifier {1}
			var Squareup_OkHostnameVerifier_Activity_1 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
			Squareup_OkHostnameVerifier_Activity_1.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
				console.log('[+] Bypassing Squareup OkHostnameVerifier {1}: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Squareup OkHostnameVerifier check not found');
			//console.log(err);
		}    
		try {
			// Bypass Squareup OkHostnameVerifier {2}
			var Squareup_OkHostnameVerifier_Activity_2 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
			Squareup_OkHostnameVerifier_Activity_2.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
				console.log('[+] Bypassing Squareup OkHostnameVerifier {2}: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Squareup OkHostnameVerifier check not found');
			//console.log(err);
		}


		

		// Android WebViewClient (quadruple bypass) //
		//////////////////////////////////////////////
		try {
			// Bypass WebViewClient {1} (deprecated from Android 6)
			var AndroidWebViewClient_Activity_1 = Java.use('android.webkit.WebViewClient');
			AndroidWebViewClient_Activity_1.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) {
				console.log('[+] Bypassing Android WebViewClient check {1}');
			};
		} catch (err) {
			console.log('[-] Android WebViewClient {1} check not found');
			//console.log(err)
		}
		try {
			// Bypass WebViewClient {2}
			var AndroidWebViewClient_Activity_2 = Java.use('android.webkit.WebViewClient');
			AndroidWebViewClient_Activity_2.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function(obj1, obj2, obj3) {
				console.log('[+] Bypassing Android WebViewClient check {2}');
			};
		} catch (err) {
			console.log('[-] Android WebViewClient {2} check not found');
			//console.log(err)
		}
		try {
			// Bypass WebViewClient {3}
			var AndroidWebViewClient_Activity_3 = Java.use('android.webkit.WebViewClient');
			AndroidWebViewClient_Activity_3.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(obj1, obj2, obj3, obj4) {
				console.log('[+] Bypassing Android WebViewClient check {3}');
			};
		} catch (err) {
			console.log('[-] Android WebViewClient {3} check not found');
			//console.log(err)
		}
		try {
			// Bypass WebViewClient {4}
			var AndroidWebViewClient_Activity_4 = Java.use('android.webkit.WebViewClient');
			AndroidWebViewClient_Activity_4.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function(obj1, obj2, obj3) {
				console.log('[+] Bypassing Android WebViewClient check {4}');
			};
		} catch (err) {
			console.log('[-] Android WebViewClient {4} check not found');
			//console.log(err)
		}
		



		// Apache Cordova WebViewClient //
		//////////////////////////////////
		try {
			var CordovaWebViewClient_Activity = Java.use('org.apache.cordova.CordovaWebViewClient');
			CordovaWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) {
				console.log('[+] Bypassing Apache Cordova WebViewClient check');
				obj3.proceed();
			};
		} catch (err) {
			console.log('[-] Apache Cordova WebViewClient check not found');
			//console.log(err);
		}




		// Boye AbstractVerifier //
		///////////////////////////
		try {
			var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier');
			boye_AbstractVerifier.verify.implementation = function(host, ssl) {
				console.log('[+] Bypassing Boye AbstractVerifier check: ' + host);
			};
		} catch (err) {
			console.log('[-] Boye AbstractVerifier check not found');
			//console.log(err);
		}




		// Apache AbstractVerifier //
		/////////////////////////////
		try {
			var apache_AbstractVerifier = Java.use('org.apache.http.conn.ssl.AbstractVerifier');
			apache_AbstractVerifier.verify.implementation = function(a, b, c, d) {
				console.log('[+] Bypassing Apache AbstractVerifier check: ' + a);
				return;
			};
		} catch (err) {
			console.log('[-] Apache AbstractVerifier check not found');
			//console.log(err);
		}




		// Chromium Cronet //
		/////////////////////    
		try {
			var CronetEngineBuilderImpl_Activity = Java.use("org.chromium.net.impl.CronetEngineBuilderImpl");
			// Setting argument to TRUE (default is TRUE) to disable Public Key pinning for local trust anchors
			CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.overload('boolean').implementation = function(a) {
				console.log("[+] Disabling Public Key pinning for local trust anchors in Chromium Cronet");
				var cronet_obj_1 = CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);
				return cronet_obj_1;
			};
			// Bypassing Chromium Cronet pinner
			CronetEngine_Activity.addPublicKeyPins.overload('java.lang.String', 'java.util.Set', 'boolean', 'java.util.Date').implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {
				console.log("[+] Bypassing Chromium Cronet pinner: " + hostName);
				var cronet_obj_2 = CronetEngine_Activity.addPublicKeyPins.call(this, hostName, pinsSha256, includeSubdomains, expirationDate);
				return cronet_obj_2;
			};
		} catch (err) {
			console.log('[-] Chromium Cronet pinner not found')
			//console.log(err);
		}



		// Flutter Pinning packages http_certificate_pinning and ssl_pinning_plugin (double bypass) //
		//////////////////////////////////////////////////////////////////////////////////////////////
		try {
			// Bypass HttpCertificatePinning.check {1}
			var HttpCertificatePinning_Activity = Java.use('diefferson.http_certificate_pinning.HttpCertificatePinning');
			HttpCertificatePinning_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function (a, b, c ,d, e) {
				console.log('[+] Bypassing Flutter HttpCertificatePinning : ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Flutter HttpCertificatePinning pinner not found');
			//console.log(err);
		}
		try {
			// Bypass SslPinningPlugin.check {2}
			var SslPinningPlugin_Activity = Java.use('com.macif.plugin.sslpinningplugin.SslPinningPlugin');
			SslPinningPlugin_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function (a, b, c ,d, e) {
				console.log('[+] Bypassing Flutter SslPinningPlugin: ' + a);
				return true;
			};
		} catch (err) {
			console.log('[-] Flutter SslPinningPlugin pinner not found');
			//console.log(err);
		}



		
		// Dynamic SSLPeerUnverifiedException Patcher                                //
		// An useful technique to bypass SSLPeerUnverifiedException failures raising //
		// when the Android app uses some uncommon SSL Pinning methods or an heavily //
		// code obfuscation. Inspired by an idea of: https://github.com/httptoolkit  //
		///////////////////////////////////////////////////////////////////////////////
		function rudimentaryFix(typeName) {
			// This is a improvable rudimentary fix, if not works you can patch it manually
			if (typeName === undefined){
				return;
			} else if (typeName === 'boolean') {
				return true;
			} else {
				return null;
			}
		}
		try {
			var UnverifiedCertError = Java.use('javax.net.ssl.SSLPeerUnverifiedException');
			UnverifiedCertError.$init.implementation = function (str) {
				console.log('\x1b[36m[!] Unexpected SSLPeerUnverifiedException occurred, trying to patch it dynamically...\x1b[0m');
				try {
					var stackTrace = Java.use('java.lang.Thread').currentThread().getStackTrace();
					var exceptionStackIndex = stackTrace.findIndex(stack =>
						stack.getClassName() === "javax.net.ssl.SSLPeerUnverifiedException"
					);
					// Retrieve the method raising the SSLPeerUnverifiedException
					var callingFunctionStack = stackTrace[exceptionStackIndex + 1];
					var className = callingFunctionStack.getClassName();
					var methodName = callingFunctionStack.getMethodName();
					var callingClass = Java.use(className);
					var callingMethod = callingClass[methodName];
					console.log('\x1b[36m[!] Attempting to bypass uncommon SSL Pinning method on: '+className+'.'+methodName+'\x1b[0m');					
					// Skip it when already patched by Frida
					if (callingMethod.implementation) {
						return; 
					}
					// Trying to patch the uncommon SSL Pinning method via implementation
					var returnTypeName = callingMethod.returnType.type;
					callingMethod.implementation = function() {
						rudimentaryFix(returnTypeName);
					};
				} catch (e) {
					// Dynamic patching via implementation does not works, then trying via function overloading
					//console.log('[!] The uncommon SSL Pinning method has more than one overload); 
					if (String(e).includes(".overload")) {
						var splittedList = String(e).split(".overload");
						for (let i=2; i<splittedList.length; i++) {
							var extractedOverload = splittedList[i].trim().split("(")[1].slice(0,-1).replaceAll("'","");
							// Check if extractedOverload has multiple arguments
							if (extractedOverload.includes(",")) {
								// Go here if overloaded method has multiple arguments (NOTE: max 6 args are covered here)
								var argList = extractedOverload.split(", ");
								console.log('\x1b[36m[!] Attempting overload of '+className+'.'+methodName+' with arguments: '+extractedOverload+'\x1b[0m');
								if (argList.length == 2) {
									callingMethod.overload(argList[0], argList[1]).implementation = function(a,b) {
										rudimentaryFix(returnTypeName);
									}
								} else if (argNum == 3) {
									callingMethod.overload(argList[0], argList[1], argList[2]).implementation = function(a,b,c) {
										rudimentaryFix(returnTypeName);
									}
								}  else if (argNum == 4) {
									callingMethod.overload(argList[0], argList[1], argList[2], argList[3]).implementation = function(a,b,c,d) {
										rudimentaryFix(returnTypeName);
									}
								}  else if (argNum == 5) {
									callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4]).implementation = function(a,b,c,d,e) {
										rudimentaryFix(returnTypeName);
									}
								}  else if (argNum == 6) {
									callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4], argList[5]).implementation = function(a,b,c,d,e,f) {
										rudimentaryFix(returnTypeName);
									}
								} 
							// Go here if overloaded method has a single argument
							} else {
								callingMethod.overload(extractedOverload).implementation = function(a) {
									rudimentaryFix(returnTypeName);
								}
							}
						}
					} else {
						console.log('\x1b[36m[-] Failed to dynamically patch SSLPeerUnverifiedException '+e+'\x1b[0m');
					}
				}
				//console.log('\x1b[36m[+] SSLPeerUnverifiedException hooked\x1b[0m');
				return this.$init(str);
			};
		} catch (err) {
			//console.log('\x1b[36m[-] SSLPeerUnverifiedException not found\x1b[0m');
			//console.log('\x1b[36m'+err+'\x1b[0m');
		}
		


	 
	});
	
}, 0);

 

위 코드의 출처는 아래 github 에서 찾아볼 수 있습니다.

https://gist.github.com/akabe1/5632cbc1cd49f0237cbd0a93bc8e4452

 

Another Android ssl certificate pinning bypass for various methods

Another Android ssl certificate pinning bypass for various methods - frida_multiple_unpinning.js

gist.github.com

 

'경로 및 정보' 카테고리의 다른 글

솔라나 스마트 컨트랙트 만들어보기  (1) 2023.05.08
Ubuntu 20.04 ARM Cross Compile 하기  (0) 2023.05.01
CAN 통신의 개요 (Controller Area Network)  (0) 2023.05.01
pentesting-ftp  (0) 2023.04.22
SBOM 이란  (0) 2023.04.17
블로그 이미지

wtdsoul

,

https://m.blog.naver.com/lagrange0115/221941482740

 

CAN 통신의 개요 (Controller Area Network)

통신은 사람이나 사물 간에 매체를 통하여 정보나 의사를 전달하는 것을 말합니다. 자동차 안에는 수많은 ...

blog.naver.com

 

 

 

 

통신은 사람이나 사물 간에 매체를 통하여 정보나 의사를 전달하는 것을 말합니다. 자동차 안에는 수많은 부품 및 제어기들이 있습니다. 엔진을 제어하는 ECU (Engine Control Unit), 변속기를 제어하는 TCU (Transmission Control Unit), 각종 ADAS (Advanced Driver Assistance System) 관련 제어기 등 수십 개에 해당하는 제어기들이 차량에 장착되고, 제어기들은 서로 데이터를 주고받으며 공유된 정보를 통해 다양한 제어를 하게 됩니다. 데이터를 주고받을 때 제어기들 간의 규칙이 있어야 원활한 통신을 할 수 있는데, 이러한 규칙을 통신 프로토콜 (Protocol)이라고 합니다. 자동차 내에는 CAN (Controller Area Network) 통신, LIN 통신, LAN 통신 등 다양한 통신 방법을 용도에 맞게 사용하고 있습니다. 그중에서 CAN 통신이 자동차에서 가장 많이 사용되고 있습니다.

CAN 통신은 자동차 부품회사인 보쉬 (BOSCH)에서 개발된 차량용 네트워크 통신 방식으로, 전기적 노이즈 발생이 많은 자동차 환경에서 신뢰성을 확보하기 위해 개발된 통신 방식입니다.

CAN 통신은 여러 개의 제어기들을 병렬로 연결하여 데이터를 주고받는 구조로 되어 있습니다. 통신 라인을 공유하는 모든 제어기들이 마스터 역할을 하고 있기 때문에 필요에 따라 언제든지 통신이 가능합니다. 쉽게 말해, 통신선상에 데이터를 띄워 놓으면, 어떤 제어기든지 필요할 때마다 데이터를 가져가 사용하는 방식입니다.

여러 개의 제어기들을 병렬로 연결하여 데이터를 주고받는 구조

제어기 내부의 CAN 통신 회로 구성

제어기 내의 CAN 통신 회로 구성은 위의 블록도와 같습니다. 가장 오른쪽은 외부 CAN BUS로 CAN H와 CAN L 신호를 주고받습니다. CAN BUS는 제어기 커넥터를 통해 연결된 후 CAN 트랜시버로 연결됩니다. 그리고 CAN 트랜시버는 마이크로컨트롤러 (MCU)와 연결됩니다. 정리하면, MCU와 CAN BUS 사이에 CAN 트랜시버가 있는 구조입니다. 그렇다면 CAN 트랜시버의 역할을 간단하게 살펴보겠습니다.

먼저 CAN H와 CAN L의 파형은 아래 그림의 오른쪽과 같습니다. CAN H는 2.5V~3.5V 전압을, CAN L는 2.5V~1.5V 전압을 사용합니다. CAN H와 CAN L의 전위차가 없을 때는 recessive (열성), CAN H와 CAN L의 전위차가 있을 때는 dominant (우성)이라고 표현합니다. 즉, CAN 통신은 두 라인의 전위차를 통해 데이터를 전달하는 것입니다.

 

CAN 통신의 Recessive와 Dominant

CAN BUS의 CAN H와 CAN L 신호가 CAN 트랜시버를 통해 recessive 인지 dominant 인지 판단을 합니다. 그리고 CAN 트랜시버의 RX를 통해 recessive 이면 HIGH, dominant 이면 LOW 신호를 MCU에 전달합니다. 반대로 MCU에서 CAN BUS로 데이터를 전송할 때는 MCU의 LOW와 HIGH 신호를 CAN 트랜시버가 CAN H와 CAN L 신호 형태에 맞게 변환해 줍니다.

출처 : TEXAS INSTRUMENTS, Indtroduction to the Controller Area Network (CAN)

CAN 트랜시버 내부 회로도

위의 CAN 트랜시버 회로와 같이, MCU의 TX에서 HIGH 신호를 보내면 FET는 비활성화되어 2.5V 풀업 저항에 의해 CAN H와 CAN L 모두 2.5V가 됩니다. 반대로 MCU의 TX에서 LOW 신호를 보내면 FET는 활성화되어 CAN H 5V, CAN L는 GND 전위가 됩니다.

CAN 프레임 형식에 대해 간단하게 알아보겠습니다. 바로 아래 그림과 같이 CAN 통신에서 요구하는 CAN 통신 프레임을 만족해야 제어기들 간에 데이터를 전송할 수 있습니다. 쉽게 말해, 서로 데이터를 어떻게 주고받을지 약속을 정하는 것과 같습니다.

CAN 프레임 형식

SOF (Start of Frame)
메시지의 시작을 표시, idle 상태 이후 동기화
Identifier
메시지의 우선순위를 설정, 이진값이 낮을수록 우선순위가 높음
RTR (Remote Transmission Request)
데이터 프레임과 리모트 프레임 구분 (데이터 프레임은 0)
IDE (Idenrifier Extension)
CAN Standard 프레임과 CAN Extended 프레임 구분
R0
Reserved bit
DLC (Data Length Code)
전송 중인 데이터의 바이트 수
Data
8byte 데이터를 전송
CRC (Cycle Redundancy Check)
16bit checksum
ACK (Acknowledgement)
승인
EOF (End of Frame)
CAN 프레임의 끝을 표시
IFS (Interframe Space)
버퍼 영역

CAN 통신은 여러 제어기들이 신호를 함께 보내고, 이를 피드백 받으면서 진행됩니다. 하지만 동시에 여러 제어기들이 신호를 송신한다면 어떻게 우선순위를 정하는지 알아보겠습니다. 아래 표와 같이 NODE 3를 가지고 Idendifier의 비트를 비교합니다.

CAN 통신 arbitration의 원리

신호가 HIGH 이면 recessive, LOW 이면 dominant 입니다. 위의 그림에서 10~6 bit 까지 3개의 NODE 상태는 모두 동일합니다. 5번 bit는 NODE 2만 HIGH (recessive)입니다. Recessive는 말 그대로 "열성"이라는 의미로 여기서부터 NODE 2의 신호 전송은 중지됩니다. 그리고 2번 bit에서는 NODE 1이 HIGH (recessive)입니다. 따라서 NODE 1의 신호 전송이 중지됩니다. 결국 여기서 우선순위는 NODE 3이 가장 높습니다. 중간에 전송을 중지한 NODE 1과 NODE 2는 다음에 재전송을 시도합니다.

※ CAN 통신에서의 에러

에러가 발생되면 에러 프레임이 전송됩니다. 에러 프레임으로 전송 실패를 인식하면 재전송의 기회를 기다립니다.

- BIT 에러 : 송신 bit와 수신 bit가 상이한 경우

- ACK 에러 : 수신 장치가 응답이 없을 때, 통신 선로가 끊기거나 접촉 불량인 경우

- FORMAT 에러 : CRC del, ACK del, EOF 영역에 0 (dominant) 값이 나타난 경우

- STUFF 에러 : Stuffing 규칙이 맞지 않은 경우

- CRC 에러 : CRC가 맞지 않은 경우

CAN 제어기 내부에는 송신 에러 카운터와 수신 에러 카운터가 각각 있습니다. 에러가 검출될 때마다 카운터가 1씩 증가하고, 에러 없이 성공적으로 전달이 완료되면 카운터가 1씩 감소합니다. 초기 상태에는 Error active 상태이며, 에러 카운터 값이 127 보다 커지면 Error passive 상태가 됩니다. 그리고 에러 카운터 값이 255를 초과하면 BUS OFF 상태로 해당 노드를 CAN 망에서 끊어버립니다.

CAN 통신의 에러 상태 처리

'경로 및 정보' 카테고리의 다른 글

Ubuntu 20.04 ARM Cross Compile 하기  (0) 2023.05.01
[frida] 프리다 안드로이드 SSL/TLS 피닝 우회 스크립트  (0) 2023.05.01
pentesting-ftp  (0) 2023.04.22
SBOM 이란  (0) 2023.04.17
Shell code Development pdf  (0) 2023.04.16
블로그 이미지

wtdsoul

,

pentesting-ftp

경로 및 정보 2023. 4. 22. 00:01

https://book.hacktricks.xyz/network-services-pentesting/pentesting-ftp

 

21 - Pentesting FTP - HackTricks

write_enable=YES - Allow commands: STOR, DELE, RNFR, RNTO, MKD, RMD, APPE, and SITE

book.hacktricks.xyz

 

21 - Pentesting FTP

 
Basic Information
The File Transfer Protocol (FTP) is a standard network protocol used for the transfer of computer files between a client and server on a computer network. It is a plain-text protocol that uses as new line character 0x0d 0x0a so sometimes you need to connect using telnet or nc -C.
Default Port: 21
 
PORT STATE SERVICE
 
21/tcp open ftp
Connections Active & Passive
In Active FTP the FTP client first initiates the control connection from its port N to FTP Servers command port – port 21. The client then listens to port N+1 and sends the port N+1 to FTP Server. FTP Server then initiates the data connection, from its port M to the port N+1 of the FTP Client.
But, if the FTP Client has a firewall setup that controls the incoming data connections from outside, then active FTP may be a problem. And, a feasible solution for that is Passive FTP.
In Passive FTP, the client initiates the control connection from its port N to the port 21 of FTP Server. After this, the client issues a passv comand. The server then sends the client one of its port number M. And the client initiates the data connection from its port P to port M of the FTP Server.
Connection debugging
The FTP commands debug and trace can be used to see how is the communication occurring.
Enumeration
Banner Grabbing
 
nc -vn <IP> 21
 
openssl s_client -connect crossfit.htb:21 -starttls ftp #Get certificate if any
Connect to FTP using starttls
 
lftp
 
lftp :~> set ftp:ssl-force true
 
lftp :~> set ssl:verify-certificate no
 
lftp :~> connect 10.10.10.208
 
lftp 10.10.10.208:~> login
 
Usage: login <user|URL> [<pass>]
 
lftp 10.10.10.208:~> login username Password
Unauth enum
With nmap
 
sudo nmap -sV -p21 -sC -A 10.10.10.10
You can us the commands HELP and FEAT to obtain some information of the FTP server:
 
HELP
 
214-The following commands are recognized (* =>'s unimplemented):
 
214-CWD XCWD CDUP XCUP SMNT* QUIT PORT PASV
 
214-EPRT EPSV ALLO* RNFR RNTO DELE MDTM RMD
 
214-XRMD MKD XMKD PWD XPWD SIZE SYST HELP
 
214-NOOP FEAT OPTS AUTH CCC* CONF* ENC* MIC*
 
214-PBSZ PROT TYPE STRU MODE RETR STOR STOU
 
214-APPE REST ABOR USER PASS ACCT* REIN* LIST
 
214-NLST STAT SITE MLSD MLST
 
214 Direct comments to root@drei.work
 
 
FEAT
 
211-Features:
 
PROT
 
CCC
 
PBSZ
 
AUTH TLS
 
MFF modify;UNIX.group;UNIX.mode;
 
REST STREAM
 
MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.mode*;UNIX.owner*;
 
UTF8
 
EPRT
 
EPSV
 
LANG en-US
 
MDTM
 
SSCN
 
TVFS
 
MFMT
 
SIZE
 
211 End
 
 
STAT
 
#Info about the FTP server (version, configs, status...)
Anonymous login
anonymous : anonymous anonymous : ftp : ftp
 
ftp <IP>
 
>anonymous
 
>anonymous
 
>ls -a # List all files (even hidden) (yes, they could be hidden)
 
>binary #Set transmission to binary instead of ascii
 
>ascii #Set transmission to ascii instead of binary
 
>bye #exit
Automated
Anon login and bounce FTP checks are perform by default by nmap with -sC option or:
 
nmap --script ftp-* -p 21 <ip>
Browser connection
You can connect to a FTP server using a browser (like Firefox) using a URL like:
 
ftp://anonymous:anonymous@10.10.10.98
Note that if a web application is sending data controlled by a user directly to a FTP server you can send double URL encode %0d%0a (in double URL encode this is %250d%250a) bytes and make the FTP server perform arbitrary actions. One of this possible arbitrary actions is to download content from a users controlled server, perform port scanning or try to talk to other plain-text based services (like http).
Download all files from FTP
 
wget -m ftp://anonymous:anonymous@10.10.10.98 #Donwload all
 
wget -m --no-passive ftp://anonymous:anonymous@10.10.10.98 #Download all
Some FTP commands
 
FTPBounce attack
Some FTP servers allow the command PORT. This command can be used to indicate to the server that you wants to connect to other FTP server at some port. Then, you can use this to scan which ports of a host are open through a FTP server.
You could also abuse this behaviour to make a FTP server interact with other protocols. You could upload a file containing an HTTP request and make the vulnerable FTP server send it to an arbitrary HTTP server (maybe to add a new admin user?) or even upload a FTP request and make the vulnerable FTP server download a file for a different FTP server. The theory is easy:
 
Its highly probably that this will throw an error like Socket not writable because the connection doesn't last enough to send the data with RETR. Suggestions to try to avoid that are:
 
 
posts.txt
495KB
Text
posts.txt
 
Filezilla Server Vulnerability
FileZilla usually binds to local an Administrative service for the FileZilla-Server (port 14147). If you can create a tunnel from your machine to access this port, you can connect to it using a blank password and create a new user for the FTP service.
Config files
 
ftpusers
 
ftp.conf
 
proftpd.conf
 
vsftpd.conf
Post-Exploitation
The default configuration of vsFTPd can be found in /etc/vsftpd.conf. In here, you could find some dangerous settings:
 
Shodan
 

'경로 및 정보' 카테고리의 다른 글

[frida] 프리다 안드로이드 SSL/TLS 피닝 우회 스크립트  (0) 2023.05.01
CAN 통신의 개요 (Controller Area Network)  (0) 2023.05.01
SBOM 이란  (0) 2023.04.17
Shell code Development pdf  (0) 2023.04.16
Braktooth-IVI-Report/  (0) 2023.04.14
블로그 이미지

wtdsoul

,

SBOM 이란

경로 및 정보 2023. 4. 17. 10:05

SBOM(SOFTWARE BILL OF MATERIALS) 이란 무엇인가 :: 오픈비 : 삽질은없다 (openbee.kr)

 

SBOM(SOFTWARE BILL OF MATERIALS) 이란 무엇인가

개요 작년 미국의 국가 사이버 보안 강화 지침(2021년 5월)이 배포된 이후, 소프트웨어 산업의 다양한 채널에서 SBOM과 관련한 자문이나 회의가 생기고 있는 상황입니다. 최근의 보안 위협은 공급

openbee.kr

 

개요

작년 미국의 국가 사이버 보안 강화 지침(2021년 5월)이 배포된 이후, 소프트웨어 산업의 다양한 채널에서 SBOM과 관련한 자문이나 회의가 생기고 있는 상황입니다. 

최근의 보안 위협은 공급망, 구축도구, 구축환경, 레파지토리등을 공격하는 추세가 많아지고 있는데 이 지침에서는 미국 연방정부가 사용하는 소프트웨어 공급망의 보안과 무결성을 개선하기 위한 조치를 지시하고 있습니다.

지침이 배포된 이후 미국 정부의 요청으로 미국의 90여개 소프트웨어 기업, 오픈소스 커뮤니티가 자문에 참여하여 의견을 제시히고, CISA, NTIA 에서는 이를 정리하여 SBOM 과 관련한 가이드라인 및 FAQ를 공개하였습니다.

 

SOFTWARE BILL OF MATERIALS | National Telecommunications and Information Administration

A “Software Bill of Materials” (SBOM) is a nested inventory for software, a list of ingredients that make up software components. The following documents were drafted by stakeholders in an open and transparent process to address transparency around sof

www.ntia.gov

 

SBOM 이란?

SBOM 은 SOFTWARE BILL OF MATERIALS 의 약자로 소프트웨어의 구성 요소를 나타내는 메타데이터를 의미하는데 이를 보다 쉽게 설명하자면 우리가 흔히 볼 수 있는 다음과 같은 제품의 성분표기를 떠올리면 됩니다.

성분표기를 통해서 알러지가 있는 사람은 해당 식품을 피하기도 하고, 공급자는 제품의 우수성을 홍보하기도 하고, 크게 성분에 신경쓰지 않고 그냥 사용하는 사용자도 있을 수 있죠.

이와 유사하게, SBOM은 공급되는 소프트웨어의 구성 목록을 잘 표시해서 공급자와 사용자가 이를 기반으로 의사결정에 활용할 수 있는 환경을 조성하는 것을 목표로 하고 있습니다.

NTIA 에서 발표한 SBOM의 필수 구성요소는 다음과 같이 구성되어 있습니다.

 

  • Supplier name
  • Component name
  • Version of the component
  • Cryptograph hash of the component
  • Any other unique identifier
  • Dependency relationship
  • Author of the SBOM data

 

이를 기반으로 작성한다면 다음과 같은 개념도로 표시할 수 있습니다.

National Telecommunications and Information Administration (NTIA) 에서는 오픈소스 소프트웨어나 상용 소프트웨어로 구분하지 않고 모든 공급되는 소프트웨어를 대상으로 광범위하게 적용할 수 있는 SBOM 적용을 위해 산업계의 여러 기업과 커뮤니티에 의견을 청취하고 이를 토대로 SBOM의 이해를 돕는 자료와 적용방법에 대하여 다양한 문서를 배포하고 있으니 아래 문서들을 참고하시기 바랍니다.

 

SPDX, OpenChain

이러한 소프트웨어 구성 목록을 기반으로 공급망의 투명성을 확보해야 한다는 필요성은 오픈소스 커뮤니티에서 10여년 전부터 논의되어 왔으며, 이를 해결하기 위해 실제 산업에서 SPDX와 OpenChain 이 많이 사용되고 있습니다.

  • SPDX는 라이선스 컴플라이언스, 보안 등과 같은 문제를 다루면서 진화해서 현재는 시장에서 가장 성숙한 SBOM으로 자리잡고 있습니다. (https://www.linuxfoundation.org/blog/what-is-an-sbom/)
  • 또한 오픈소스 라이선스 준수를 위한 ISO 국제표준(https://www.iso.org/standard/81039.html) 으로 오픈체인이 있으며, 이는 소프트웨어 공급망의 투명성을 강화하기 위하여 오픈소스 커뮤니티에서 고민하던 결과물입니다.

SBOM이 소프트웨어 보안의 모든 문제를 해결할 수는 없지만 보다 안전한 소프트웨어 사용에 필요한 기본을 제공하는 것은 분명히 필요한 일이며, 다양한 산업계의 의견을 토대로 만들어진 SBOM을 기반으로 소프트웨어 공급망의 투명성을 강화할 수 있는 미국의 이번 정책은 향후 IT 산업과 디지털 인프라의 소프트웨어 관리에 있어서 매우 중요하다고 생각됩니다.

'경로 및 정보' 카테고리의 다른 글

CAN 통신의 개요 (Controller Area Network)  (0) 2023.05.01
pentesting-ftp  (0) 2023.04.22
Shell code Development pdf  (0) 2023.04.16
Braktooth-IVI-Report/  (0) 2023.04.14
Hackers Are Stealing Cars by Injecting Code Into Headlight Wiring  (0) 2023.04.10
블로그 이미지

wtdsoul

,

Shellcode Development.pdf - Google Drive

 

Shellcode Development.pdf

 

drive.google.com

Shellcode Development #2.pdf - Google Drive

 

Shellcode Development #2.pdf

 

drive.google.com

 

 

'경로 및 정보' 카테고리의 다른 글

pentesting-ftp  (0) 2023.04.22
SBOM 이란  (0) 2023.04.17
Braktooth-IVI-Report/  (0) 2023.04.14
Hackers Are Stealing Cars by Injecting Code Into Headlight Wiring  (0) 2023.04.10
ASPICE 개요  (0) 2023.04.03
블로그 이미지

wtdsoul

,

Braktooth Hunting in the Car Hacker's Wonderland (rollingpwn.github.io)

 

Braktooth Hunting in the Car Hacker's Wonderland

INTRODUCTION Years ago, a team of researchers at SUTD (Asset-Group) discovered and disclosed the family of vulnerabilities in the classic Bluetooth link manager layer. They've released a paper and POC named "Braktooth: Causing Havoc on Bluetooth link manag

rollingpwn.github.io

 

INTRODUCTION

Years ago, a team of researchers at SUTD (Asset-Group) discovered and disclosed the family of vulnerabilities in the classic Bluetooth link manager layer. They've released a paper and POC named "Braktooth: Causing Havoc on Bluetooth link manager" The paper is very detailed and enjoyable to read. I highly recommend it to anyone into Bluetooth security. The Braktooth is a codename for 16 classic Bluetooth vulnerabilities. It will cause affect BT devices continuously crash or deadlock. Furthermore, at least in one case, attackers can remotely execute arbitrary code and erase all the data on the targeted devices. These bugs are present in various BT Chipsets across many manufacturers such as Intel, Qualcomm, TI, Infineon, etc.

Since my main interest focused on vehicle security, after reading through the Braktooth paper, one thing immediately got my attention. They mentioned in the paper, Braktooth not only affects laptops, and smartphones but also Infotainment units in Automobiles, even the audio system in airplanes is affected. For IVIs, they listed the Volvo FH as an example in the paper. This got me wondering if any other popular cars out there are also affected by Braktooth.

FIRST-BLOOD

Before we jump on the cars, we need to get familiar with Braktooth. The actual environment is quite simple to set it up. In the paper, they mentioned some Chipset from Mediatek that are affected. My laptop Lenovo L14 happened to use the Ralink chipset for Bluetooth communication. Since Ralink is part of the Mediatek group, which make it is the perfect target for the test run.


Because there are 16 POCs from the Braktooth vulnerabilities, we've to go through all of them. And we found one of the vulnerabilities called Invalid-Timing-Accuracy almost always work. The vulnerable chipsets do not properly handle the reception of a malformed LMP timing accuracy response followed by multiple re-connections to the target link slave.

This allows attackers to exhaust device BT resources. The attacker can trigger a crash or disturb other BT devices connected to the target chipset. The best part is attacker only needs to know the BDAddress of the target device. No authentication is required to launch the attack. As the video below demonstrated, the Bluetooth connection between the laptop and speaker stop functioning and eventually disconnected the connection.

INVESTIGATION

People always ask us how can Star-V Lab access so many cars. And this project is a perfect chance to show how we achieved it. The easiest place to start would be for the Car components to sit on the test bench table. For example, we happened to have a 2nd hand Nissan IVI in the lab. As we can see, after we fired the Invalid-Timing-Accuracy POC, the Nissan IVI kind of frozen, and it won't detect any Bluetooth devices nearby anymore.

The 2nd place to look for potential targets is the company car parking lot. If we ask nicely, most of the staff even the company CEO are interested to see if their car can hacked ;) At that time, we got 2 Tesla cars and 1 Changan Uni-T accessible for testing. For Tesla Model 3 and Model X, only the Invalid-Setup-Complete POC worked. All other POCs failed.

 

But for Changan Uni-T almost all the vulns works. Only 6 of the POC has no impaction. As the video shows, Braktooth disconnected the connection. Interestingly the Bluetooth logo on the IVI screen still shows everything is fine, but in fact, the connection has been disconnected.

If we got enough budget we can rent some cars for testing. But what if our budget is short and we need to test the latest modern cars? An advantage of living in a big city is we are surrounded by Car dealer shops. And these are perfect spots for us.

This time we found 4 cars affected by Braktooth. The first one is NIO ET5, which is a Chinese brand and quite popular in China.

For NIO it will disconnect the Bluetooth connection straight away.

Then we went to the Volkswagen to test ID4X. Compare to other Android-based IVI, ID4X seems a bit hard to use.

Again once we fired the attack, the Bluetooth connection disconnected.

Finally, we tested a new smart car player in the Chinese market called ARCFOX. As the video shows the music start been funny after we fired the attack.

One thing special regarding this brand is one of the car models using the Huawei HarmonyOS as IVI's system.

However, when coming to low-level Bluetooth attack, Huawei HarmonyOS makes no difference.

Another nice spot for testing is the Car exhibition. The good thing about the exhibition is we may able to test some fancy sports cars, which normally we won't be able to touch.

Here we've tested the Neta V and Leapmotor C01 cars.


As we can see both of them experienced the disturb first then the connection disconnected completely.

FINAL-FHOUGHT

As whitehat security researchers, we like to follow the responsible disclosure procedure. Unfortunately unlike the Internet companies, most car companies still live in a stone age. They neither don't have a bounty program nor contact info for reporting bugs. Therefore, we filed a report to their customer service and hope someone can see it. But we like to give a thumbup to the Tesla and NIO. These two companies have set up bug bounty programs and given a very quick response to our bug report. However, Nio replied that this bug has out of their scope.

And Tesla thinks this is not a security issue, since the braktooth was only able to cause the Tesla Bluetooth audio jitters. We kind of agreed on this point, so let's continue our journey and digging deeper. Spoiler alert, we did find other issues on some of those IVIs above. And at least caused one of the fancy car's IVI to go black screen. Stay tuned for our future report ;)

 

 

블로그 이미지

wtdsoul

,