사용방법

dependencies
{
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
}

Application 시작 부분에 설정

public class mTransekyApp extends Application
{
@Override
public void onCreate()
{

  if (LeakCanary.isInAnalyzerProcess(this))
  {  
    return;  
  }  
  LeakCanary.install(this);  

}
}

'개발 > Android' 카테고리의 다른 글

DEX 구조 및 분석  (0) 2021.06.04
[android] 악성코드 분석 - 1  (0) 2021.05.26
jni 유용한 코드  (0) 2020.11.27
ARM64 Calling Convention  (0) 2020.09.14
#include <iostream>
#include <jni.h>
#include <stdio.h>
#include <windows.h>
#include "HelloJNI.h"
 
using namespace std;
 
static jclass intClass;
 
JNIEXPORT jdouble JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject obj, jint n1, jstring s){
//get the jstring
const char *str = env->GetStringUTFChars(s, 0);
if (str == NULL) return 0.0;
cout << "Hello " << str << ", i = " << n1 << endl;
//printf("Hello %s, i=%d\n", str, n1);
env->ReleaseStringUTFChars(s, str);
 
/*string outCppStr;
cout << "Enter a String: ";
cin >> outCppStr;
return env->NewStringUTF(outCppStr.c_str());
*/
return n1 + 1.0;
}
 
JNIEXPORT void JNICALL Java_HelloJNI_showPrimitives
(JNIEnv * env, jobject obj, jint i, jbyte b, jshort s, jlong l, jfloat f, jdouble d, jchar c, jboolean bo){
cout << "Integer:" << i << endl;
cout << "Byte:" << b << endl;
cout << "Short:" << s << endl;
cout << "Long:" << l << endl;
cout << "Float:" << f << endl;
cout << "Double:" << d << endl;
cout << "Char:" << c << endl;
cout << "Boolean:" << (bo?"true":"false") << endl;
}
 
JNIEXPORT jdoubleArray JNICALL Java_HelloJNI_sumArray
(JNIEnv * env, jobject obj, jintArray arr){
double sum = 0.0;
 
//Convert the incoming JNI jintarray to C's jint[]
jint *cArray = env->GetIntArrayElements(arr, NULL);
if (NULL == arr) return NULL;
jsize length = env->GetArrayLength(arr);
 
//Perform operations
for (int i = 0; i < length; i++){
sum += cArray[i];
}
 
jdouble average = (jdouble) sum / length;
 
jdouble arrValues[] = {sum, average};
//Release resoruces
env->ReleaseIntArrayElements(arr, cArray, 0);
 
//Convert C's array jdouble[] to JNI jdoublearray
jdoubleArray outArray = env->NewDoubleArray(2); //allocate
if (NULL == outArray) return NULL;
env->SetDoubleArrayRegion(outArray, 0, 2, arrValues); //copy portion (from start to length)
 
cout << "Length: " << length << endl;
return outArray;
}
 
 
//Modify variable instance
JNIEXPORT void JNICALL Java_HelloJNI_modifyInstanceVariable(JNIEnv* env, jobject thisObj){
//get reference to "this" object's class
jclass thisClass = env->GetObjectClass(thisObj);
 
//get Field ID of the instance variable "number"
jfieldID fieldNumber = env->GetFieldID(thisClass, "number", "I"); //For a Java class, the field descriptor is in the form of "L<fully-qualified-name>;", with dot replaced by forward slash (/), e.g.,, the class descriptor for String is "Ljava/lang/String;". For primitives, use "I" for int, "B" for byte, "S" for short, "J" for long, "F" for float, "D" for double, "C" for char, and "Z" for boolean. For arrays, include a prefix "[", e.g., "[Ljava/lang/Object;" for an array of Object; "[I" for an array of int. You can list the method signature for a Java program via javap utility (Class File Disassembler) with -s (print signature) and -p (show private members)
 
if (NULL == fieldNumber) return;
 
//get int value given by FieldID
jint number = env->GetIntField(thisObj, fieldNumber);
//cout << "Number:" << number << endl;
 
//change the variable
number = 11;
env->SetIntField(thisObj, fieldNumber, number);
 
//Get the fieldID of the instance variable "message"
jfieldID fieldMessage = env->GetFieldID(thisClass, "message", "Ljava/lang/String;");
if (NULL == fieldMessage) return;
 
//get string variable from fieldMessage
jstring message = (jstring) env->GetObjectField(thisObj, fieldMessage);
 
//create a C++ string with JNI string
const char* cppStr = env->GetStringUTFChars(message, NULL);
if (NULL == cppStr) return;
 
//cout << "Message = " << cppStr << endl;
 
//Release resources
env->ReleaseStringUTFChars(message, cppStr);
 
//Create a new cpp String and assign to the JNI string
message = env->NewStringUTF("Hello from C++");
if (NULL == message) return;
 
env->SetObjectField(thisObj, fieldMessage, message);
 
}
 
 
//Modify static variable
JNIEXPORT void JNICALL Java_HelloJNI_modifyStaticVariable(JNIEnv *env, jobject thisObj){
 
//get reference to the class
jclass cls = env->GetObjectClass(thisObj);
 
//read variable value
jfieldID fieldNumber = env->GetStaticFieldID(cls, "staticNumber", "D");
if (NULL == fieldNumber) return;
 
jdouble number = env->GetStaticDoubleField(cls, fieldNumber);
//cout << "Static Number: " << number << endl;
 
number = 3.14;
//modifier static variable
env->SetStaticDoubleField(cls, fieldNumber, number);
 
}
 
 
//callback java methods
JNIEXPORT void JNICALL Java_HelloJNI_nativeMethod(JNIEnv *env, jobject thisObj){
//get reference to "this" object's class
jclass thisClass = env->GetObjectClass(thisObj);
jmethodID mCallback = env->GetMethodID(thisClass, "callback", "()V");
if (NULL == mCallback) return;
env->CallVoidMethod(thisObj, mCallback);
 
//call "callback(String)"
jmethodID mCallbackMsg = env->GetMethodID(thisClass, "callback", "(Ljava/lang/String;)V");
if (NULL == mCallbackMsg) return;
env->CallVoidMethod(thisObj, mCallbackMsg, env->NewStringUTF("Hello from ++") );
 
 
//call "callbackAverage(int, int)"
jmethodID mCallbackAverage = env->GetMethodID(thisClass, "callbackAverage", "(II)D");
if (NULL == mCallbackAverage) return;
cout << "Average: " << env->CallDoubleMethod(thisObj, mCallbackAverage, 2, 3) << endl;
 
//call static method "callbackStatic"
jmethodID mCallbackStatic = env->GetStaticMethodID(thisClass, "callbackStatic", "()Ljava/lang/String;");
if (NULL == mCallbackStatic) return;
//type cast is important here in c++
jstring in_str = (jstring) env->CallStaticObjectMethod(thisClass, mCallbackStatic);
const char* out_str = env->GetStringUTFChars(in_str, NULL);
if (NULL == out_str) return;
cout << "callback static string: " << out_str << endl;
env->ReleaseStringUTFChars(in_str, out_str);
 
//call super class method
jmethodID mCallbackBaseClassMethod = env->GetMethodID(thisClass, "callBaseClass" ,"()V");
if (NULL == mCallbackBaseClassMethod) return;
env->CallNonvirtualVoidMethod(thisObj, thisClass, mCallbackBaseClassMethod);
}
 
JNIEXPORT jobject JNICALL Java_HelloJNI_getIntegerObject(JNIEnv *env, jobject thisObj, jint number){
 
//get a reference for java.lang.Integer class
jclass tempIntClass = env->FindClass("java/lang/Integer");
 
//you can save a integer class reference to a global reference for later use (you can't do that for jmethodID and jfieldID they aren't objects)
intClass = (jclass) env->NewGlobalRef(tempIntClass);
//no longer need the local reference
env->DeleteLocalRef(tempIntClass);
 
//get the methodID of the constructor which takes an int
jmethodID mInit = env->GetMethodID(intClass, "<init>", "(I)V");
if (NULL == mInit) return NULL;
//call back constructor to allocate a new instance with int argument
jobject intObj = env->NewObject(intClass, mInit, number);
 
//call to call ToString() on this object
jmethodID mToString = env->GetMethodID(intClass, "toString", "()Ljava/lang/String;");
if (NULL == mToString) return NULL;
 
jstring in_str = (jstring) env->CallObjectMethod(intObj, mToString);
const char* out_str = env->GetStringUTFChars(in_str, NULL);
cout << "Number in C++: " << out_str << endl;
 
return intObj;
}
 
//call a method with Array of Object argument
JNIEXPORT jobjectArray JNICALL Java_HelloJNI_sumAndAverage(JNIEnv *env, jobject thisObj, jobjectArray intArray){
//reference to java's Integer
jclass intClass = env->FindClass("java/lang/Integer");
 
//use Integer.intValue() to retreive the int
jmethodID mIntValue = env->GetMethodID(intClass, "intValue", "()I");
if (NULL == mIntValue) return NULL;
 
//get the size of object array
jsize length = env->GetArrayLength(intArray);
jint sum = 0;
for (int i = 0; i < length; i++){
jobject intObj = env->GetObjectArrayElement(intArray, i);
if (NULL == intObj) return NULL;
sum += env->CallIntMethod(intObj, mIntValue); // may need a cast!
}
double average = (double) sum / length;
jclass classDouble = env->FindClass("java/lang/Double");
//allocate a jobjectArray of 2 Double
jobjectArray outArray = env->NewObjectArray(2, classDouble, NULL);
 
jmethodID mDoubleInit = env->GetMethodID(classDouble, "<init>", "(D)V");
if (NULL == mDoubleInit) return NULL;
jobject objSum = env->NewObject(classDouble, mDoubleInit, (double) sum);
jobject objAve = env->NewObject(classDouble, mDoubleInit, average);
//set to the jobjectArray
env->SetObjectArrayElement(outArray, 0, objSum);
env->SetObjectArrayElement(outArray, 1, objAve);
 
return outArray;
}
 
JNIEXPORT void JNICALL Java_HelloJNI_methodException(JNIEnv *env, jobject obj){
 
jthrowable exc;
jclass cls = env->GetObjectClass(obj);
jmethodID mid = env->GetMethodID(cls, "callbackException", "()V");
if (mid == NULL) return;
//try {
env->CallVoidMethod(obj, mid);
//} catch (const std::exception& e){
//cout << "Exception thrown from native code" << endl;
//}
exc = env->ExceptionOccurred();
if (exc) {
jclass newCls = env->FindClass("java/lang/IllegalArgumentException");
if (newCls == NULL) return; //unable to find exception, so just leave
env->ExceptionDescribe();
env->ExceptionClear();
cout << "Exception thrown from native code" << endl;
//raise the an IllegalArgumentException
//env->ThrowNew(newCls, "Exception thrown from native code");
}
}
 
//call method with ArrayList type argument
JNIEXPORT jobject JNICALL Java_HelloJNI_makeList(JNIEnv *env, jobject thisObj, jint i){
 
jclass arrClass = env->FindClass("java/util/ArrayList");
if (arrClass == NULL) return NULL;
 
jmethodID initArr = env->GetMethodID(arrClass, "<init>", "(I)V");
if (initArr == NULL) return NULL;
 
jmethodID arrSize = env->GetMethodID (arrClass, "size", "()I");
if (arrSize == NULL) return NULL;
 
jobject arr = env->NewObject(arrClass, initArr);
 
jmethodID arrAdd = env->GetMethodID(arrClass, "add", "(Ljava/lang/Object;)Z");
if (arrAdd == NULL) return NULL;
 
jmethodID arrGet = env->GetMethodID(arrClass, "get", "(I)Ljava/lang/Object;");
if (arrGet == NULL) return NULL;
 
for (int j = 1; j <= i; ++j) {
jclass intClass = env->FindClass("java/lang/Integer");
jmethodID mInit = env->GetMethodID(intClass, "<init>", "(I)V");
jobject intObj = env->NewObject(intClass, mInit, j);
jboolean reslt = (jboolean) env->CallBooleanMethod(arr, arrAdd, intObj);
if (!reslt)
return NULL;
}
 
jint size = (jint) env->CallIntMethod(arr, arrSize);
cout << "ArrayList size: " << size << endl;
 
return arr;
 
}

 

 

 

class ListJni {
public:
// Get the java class id of java.util.List.
static jclass getListClass(JNIEnv* env) {
jclass jclazz = env->FindClass("java/util/List");
assert(jclazz != nullptr);
return jclazz;
}
 
// Get the java class id of java.util.ArrayList.
static jclass getArrayListClass(JNIEnv* env) {
jclass jclazz = env->FindClass("java/util/ArrayList");
assert(jclazz != nullptr);
return jclazz;
}
 
// Get the java class id of java.util.Iterator.
static jclass getIteratorClass(JNIEnv* env) {
jclass jclazz = env->FindClass("java/util/Iterator");
assert(jclazz != nullptr);
return jclazz;
}
 
// Get the java method id of java.util.List.iterator().
static jmethodID getIteratorMethod(JNIEnv* env) {
static jmethodID mid = env->GetMethodID(
getListClass(env), "iterator", "()Ljava/util/Iterator;");
assert(mid != nullptr);
return mid;
}
 
// Get the java method id of java.util.Iterator.hasNext().
static jmethodID getHasNextMethod(JNIEnv* env) {
static jmethodID mid = env->GetMethodID(
getIteratorClass(env), "hasNext", "()Z");
assert(mid != nullptr);
return mid;
}
 
// Get the java method id of java.util.Iterator.next().
static jmethodID getNextMethod(JNIEnv* env) {
static jmethodID mid = env->GetMethodID(
getIteratorClass(env), "next", "()Ljava/lang/Object;");
assert(mid != nullptr);
return mid;
}
 
// Get the java method id of arrayList constructor.
static jmethodID getArrayListConstructorMethodId(JNIEnv* env, jclass jclazz) {
static jmethodID mid = env->GetMethodID(
jclazz, "<init>", "(I)V");
assert(mid != nullptr);
return mid;
}
 
// Get the java method id of java.util.List.add().
static jmethodID getListAddMethodId(JNIEnv* env) {
static jmethodID mid = env->GetMethodID(
getListClass(env), "add", "(Ljava/lang/Object;)Z");
assert(mid != nullptr);
return mid;
}
};
 
class ByteJni {
public:
// Get the java class id of java.lang.Byte.
static jclass getByteClass(JNIEnv* env) {
jclass jclazz = env->FindClass("java/lang/Byte");
assert(jclazz != nullptr);
return jclazz;
}
 
// Get the java method id of java.lang.Byte.byteValue.
static jmethodID getByteValueMethod(JNIEnv* env) {
static jmethodID mid = env->GetMethodID(
getByteClass(env), "byteValue", "()B");
assert(mid != nullptr);
return mid;
}
};
// ==================== Java ArrayList<String> ==> C++ vector<string> ====================
static jclass java_util_ArrayList;
static jmethodID java_util_ArrayList_;
jmethodID java_util_ArrayList_size;
jmethodID java_util_ArrayList_get;
jmethodID java_util_ArrayList_add;
static thread_local JNIEnv* env;
 
void init() {
java_util_ArrayList = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
java_util_ArrayList_ = env->GetMethodID(java_util_ArrayList, "<init>", "(I)V");
java_util_ArrayList_size = env->GetMethodID (java_util_ArrayList, "size", "()I");
java_util_ArrayList_get = env->GetMethodID(java_util_ArrayList, "get", "(I)Ljava/lang/Object;");
java_util_ArrayList_add = env->GetMethodID(java_util_ArrayList, "add", "(Ljava/lang/Object;)Z");
}
 
std::vector<std::string> java2cpp(jobject arrayList) {
jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
std::vector<std::string> result;
result.reserve(len);
for (jint i=0; i<len; i++) {
jstring element = static_cast<jstring>(env->CallObjectMethod(arrayList, java_util_ArrayList_get, i));
const char* pchars = env->GetStringUTFChars(element, nullptr);
result.emplace_back(pchars);
env->ReleaseStringUTFChars(element, pchars);
env->DeleteLocalRef(element);
}
}
 
// ==================== C++ vector<string> ==> Java ArrayList<String> ====================
jobject cpp2java(std::vector<std::string> vector) {
jobject result = env->NewObject(java_util_ArrayList, java_util_ArrayList_, vector.size());
for (std::string s: vector) {
jstring element = env->NewStringUTF(s.c_str());
env->CallBooleanMethod(result, java_util_ArrayList_add, element);
env->DeleteLocalRef(element);
}
return result;
}

 

'개발 > Android' 카테고리의 다른 글

DEX 구조 및 분석  (0) 2021.06.04
[android] 악성코드 분석 - 1  (0) 2021.05.26
안드로이드 Leak 확인 - LeakCanary  (0) 2021.01.08
ARM64 Calling Convention  (0) 2020.09.14

AppleStore 에 올라간 파일은 Fairplay DRM 방식으로 암호화 되어 있다. 해당 바이너리를 분석하기 위해서는 암호화를 풀어야 한다. 

바이너리는 메모리에 로딩된 시점에는 FairePlay  DRM 이 풀린상태이다. 이때 메모리 덤프를 저장 하면 복호화된 바이너리를 얻을 수 있다. 

 

otool 명령어를 이용하면 해당 바이너리의 Fairpaly DRM 여부를 확인 할 수 있다. 

 

otool -l "파일이름" | grep -A4 LC_ENCRYPTION_INFO

 

IPHONE  otool 설치 

 - cydia 에서 Drawin CC Tool 설치 

 

 

frida-ios-dump 사용

 

다운로드 

https://github.com/AloneMonkey/frida-ios-dump 

 

AloneMonkey/frida-ios-dump

pull decrypted ipa from jailbreak device. Contribute to AloneMonkey/frida-ios-dump development by creating an account on GitHub.

github.com

 

iTunesDriver64

itunnel_mux_rev71

drive.google.com/file/d/1fnoT4h83sA1yOlfmSwZ-pAVwF4gSu_FX/view?usp=sharing

 

itunnel_mux_rev71.zip

 

drive.google.com

drive.google.com/file/d/1fnoT4h83sA1yOlfmSwZ-pAVwF4gSu_FX/view?usp=sharing

 

itunnel_mux_rev71.zip

 

drive.google.com

* 위파일을 모두 설치한다. 

 

1. ssh 포트를 2222 포트 포워딩 한다. itunnel_mux_rev71. 이용    

   - itunnel_mux.exe --iport 22 --lport 2222

     만약 덤프가 안떠진다면 iport를 44로 해보면 된다. 

2. 받은 frida-dump 의 필요한 파일들을 설치한다.  받은 frida-dump 폴더에 requirements.txt 활용 

   - pip install -r requirements.txt

 

3.  덤프를 저장할 앱 검색 

   - frida-ps -Uai

 

 

3.덤프 저장 

- python dump.py com.xxxxx.xxxx

 

 

 

덤프가 저장된것을 볼수 있다. 

이제 이 복호화된 파일을 가지고 분석을 진행 할 수 있다. 

 

 

*****************************************************************************************************************************************

windows 환경인 경우 dump.py 의 명령어 중 ls, chmod 등의 리눅스 명령어가 포함되어 있다. 이로 인해 오류가 발생하는데 windows 환경에서 해당 명령을 사용 할 수 있도록 환경을 구축 해야 한다.
https://github.com/bmatzelle/gow/releases

 

Releases · bmatzelle/gow

Unix command line utilities installer for Windows. - bmatzelle/gow

github.com

 

 

 

Gow-0.8.0.exe
8.68MB

 

*****************************************************************************************************************************************

 

 

 

'개발 > Frida' 카테고리의 다른 글

[DIVA2] 1. Local DAta Storage  (0) 2022.09.29
FridaLab  (0) 2021.08.06
[Frida_IOS] 앱분석_(1)  (0) 2020.09.28
[Frida_IOS] 환경 구축  (0) 2020.09.28

 

 

About

There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?

To do this level, log in as the level01 account with the password level01. Files for this level can be found in /home/flag01.

 

 

 

[풀이]

해당 소스의 실행파일이 /home/flag01 이다. 

일단 파일 정보를 확인 하면 다음과 같다. 

 

 

 

 

 

 

 

파일의 소유자는 flag01 이고 그룹은 level01 이 가지고 있다. 

현재 우리는 level01 계정으로 로그인 한 상태이다. 

level01 그룹 권하은 현재 읽기와 실행만 가능한 상태이다 r_x

소유자 권한에는 rws 읽고 쓰기 실행이 가능한데 실행권한에 x가 아닌 s 되어 있다. 이것은 

Setuid 를 설정한 것인데 이는 소유자가 아닌 다른 사용자 (그룹) 가 실행시에는 flag01 소유자 권한을 갖는다는것이다. 

즉 level01 로 로그인한 사용자가 flag01 를 실행 할 때는 flag01 권한을 가지고 실행이 된다는 뜻이다. 

여기서 소스는 분석 해 보면 

gid = getegid();

uid = geteuid();

 

geteuid() 는 Effective Uid를 가져오라는 뜻이다.  해당 실행프로그램이 실행 시점에 가지고 있는 소유자 id를 가져오라는 뜻이다. level01 로 해당 파일을 실행 시키면 Setuid 권한에 의해 실행시점의 소유자는 flag01 이 된다. 

결국 geteuid는 flag01 를 반환 하게 된다. 

 

setresuid(uid, uid, uid) 

현재 얻어온 flag01 소유자로 res uid를 설정 하라는 뜻이다 . 

여기서 res 는 

R = RUID      -> 실제 아이디 (여기서 level01)

E = UID        -> flag01

S = Saved ID -> 저장용 (일단 신경 안써도 된다)

 

flag01 을 실행하면  

RUID = level01

EUID = flag01

SUID = flag01

를 가지게 된다.  RUID 또는 EUID 를 둘중 우선수위를 누구를 할지는 시스템에 따라 다를 수 있다. 

 

그래서 setresuid 함수를 통해 RES 를 flag01(EUID)로 설정 하고 있다. 

그러면 다음 코드부터는 flag01 권한으로 실행이 수행된다. 

 

다음 코드는 system("/usr/bin/env echo and now what.?"); 함수를 수행 하고 있다. 

 

env 현재 로그인 사용자의 환경에 대한 정보를 가져온다. 

 

 

 

대충 이런 내용들이다. 

 

env 에 인자를 전달 하면 해당 환경에서 해당 명령어를 실행 한다. 

소스에서 evn echo 명령이 들어있는데 있는 echo 명령을 실행 하겠다는 뜻이다. 

그래서 실행을 하면 echo 뒤에 있는 and now what? 이라는 문자열이 출려되었다. 

우리는 이 echo 명령을 쉘 명렁어로 바꾸어 놓으면 flag01 소유권하을 가진 쉘을 획득 할 수 있다. 

일단 쉘 스크립티를 만든다. 

 

 

알단 /tmp 폴더로 이동 하면 파일을 만든다. (해당 폴더에는 level01 로는 쓰기 권한이 없다.)

 

 

 

 

위와 같이 bash 쉘을 실행시킬수 있는 스크립트를 만든다. 

파일 이름은 echo

위와 같이 실행 권한을 준다. 

 

이제 이 파일이 flag01 소유권한으로 실행될수만 있으면 flag01 궈한을 가진 쉘을 획득 할 수있다. 

 

 system("/usr/bin/env echo and now what.?"); 

 

env 명령은 절대 경로로 설정되어 있도 echo 명령은 path 환경에서 찾아 해당 폴더의 echo가 실행 된다. 

우리는 path 의 경로에 /tmp 를 추가하면 /tmp 에 있는 echo 가 실행 되도록 하면 된다. 

PATH=/tmp:$PATH

 

위 명령을 주면 /tmp 경로가 기존 PATH 에서 가장 맨 왼쪽에 추가 된다. 맨 왼쪽에 있는 것일 수록 우선수위가 가 높다. 왼쪽에 에서 부터 파일을 찾아 실행한다. 그러므로 echo 명령을 수행하면 /tmp 에 있는 echo 가 실행 될 것이다. 

 

 

이제 다시 flag01 를 수행해 보자 

 

실행후 flag01 권한을 가진shell를 획득 한걸 알 수있다 

만약 해당 파일의 소유자가 root 였다면 우리는 root권한을 가진 shell을 획득 할 것이다. 

 

 

About

This level requires you to find a Set User ID program that will run as the “flag00” account. You could also find this by carefully looking in top level directories in / for suspicious looking directories.

Alternatively, look at the find man page.

To access this level, log in as level00 with the password of level00

 

[풀이 ]

flags00 에서 실행하고있는 Set User ID 프로그램 파일을 찾아라. 즉 SUID 걸린 파일을 찾아라. 

 

[파일의 권한 설정]

find / -user flag00 -perm -4000 2>/dev/null 

 

find : 파일 검색

/ : 루트부터 전체 검색 

-user flag00 : 사용자가 flag00 검색

-perrm -4000 : SetUid 걸린 파일 검색 

2>/dev/null :  에러나는 파일 출력 안함 

 

SetUid 가 걸린 파일은 실행시 현재 접속한 사용자가 아니라, 해당 파일의 소유자 권한으로 실행 하라는 의미. 

 

 

 

flag00 명령을 실행하면 getflag를 실행 하라고 함 

 

[getflag 실행 후 모습]

 

 

 

 

준비물 : vmware 

nubula image : exploit-exercises.lains.space/nebula/

 

Nebula - Exploit Exercises

About Nebula takes the participant through a variety of common (and less than common) weaknesses and vulnerabilities in Linux. It takes a look at SUID files Permissions Race conditions Shell meta-variables $PATH weaknesses Scripting language weaknesses Bin

exploit-exercises.lains.space

 

nebula 이미지 선택
linux kernel 2.6

 

 

 

 

부팅시 live 선택 

 

첫번째 로그인은 

level00 / level00

 

 

 

 

분석할 앱을 설치한 후 Applicaions(User) 폴더에서 Modified Data 눌러 가장 최신 업데이트된 폴더로 들어간다. 

 

 

 

그럼 저렇게 실제 폴더로 이동 하게 되고 거기서 가장 큰 파일을 보통 실행 파일이 이다. 

해당 파일을 가져온다. 

 

 

Ghidra를 이용 해당 실행파을을 분석 

ghidra-sre.org/

 

Ghidra

Getting Help Ghidra provides context-sensitive help on menu items, dialogs, buttons and tool windows. To access the help, press F1 or Help on any menu item or dialog. Visit our Wiki Issue Tracker

ghidra-sre.org

 

'

Gidra 에 실행파일을 open 

 

 

 

파일에 대해 기본 분석을 진행하면 바이너리 정보를 볼 수 있다. 

 

 

 

분석이 끝나면 functions 에서 분석하고자 하는 함수를 찾는다. 

 

분석할 함수를 첫 부분에 마우스를 올려놓으면 imagebase에서의 옵셋 값을 볼 수 있다. 

우리가 분석할 위치는 ImageBase + 옵셋 이기 때문에 해당 값을 기록 한다. 

여기서는 0x28d9f0  이다. 

 

실행) frida -U -f com.xxx.xxx -l [js파일]

 

위 코드는 frida 로 분석할 JS 코드이다. 

해당 함수 위치의 ( + 0x28d8f0) 함수가 호출되면 현재의 context(Register 데이터들 )를 로그로 찍 도록 하였다. 

 

해당 함수가 호출 될 때마다 레지스트에 있는 데이터들이 찍혀 있는 걸 볼 수 있다. 

 

특정 레지스트리에 메모리 데이터를 보고 싶다면 다음코드를 삽입하면 된다. 

 

console.log(hexdump(ptr(this.context.x1)));

x1 레지스트의 메모리값을 표현. 

 

 

 

아래 코드는 x1 레지스트가 가지고 있는 메모리값에서 +10 만큼 한 위치부터 문자열을 찍어내는 스크립트 이다. 

var pos = this.context.x1 + 10;

console.log('\n' + Memory.readUtf8String(pos));

 

 

 

 

 

 

 

 

 

 

 

 

'개발 > Frida' 카테고리의 다른 글

[DIVA2] 1. Local DAta Storage  (0) 2022.09.29
FridaLab  (0) 2021.08.06
[IOS] Fairplay DRM 복호화  (1) 2020.10.08
[Frida_IOS] 환경 구축  (0) 2020.09.28

독립된 파이썬 환경 구축 

 

아나콘다 설치 

docs.anaconda.com/anaconda/install/

 

Installation — Anaconda documentation

Installation Review the system requirements listed below before installing Anaconda Individual Edition. If you don’t want the hundreds of packages included with Anaconda, you can install Miniconda, a mini version of Anaconda that includes just conda, its

docs.anaconda.com

파이썬 환경 구축 

anaconda shell 모드에서 

 

conda crate -n py371 python=3.1. -y  (파이썬 3.7.1 버전으로생성)

activate py371                               (위에 생성한 환경으로 적용)

python --verion  (파이썬 버전 확인)

 

프리다 설치 

pip install frida == 12.11.16 (구성할 프리다 버전 설정)

pip install frida-tools 

frida --verion 

 

아키텍쳐에 맞는 프리다 서버 다운로드 

github.com/frida/frida/releases

 

Releases · frida/frida

Clone this repo to build Frida. Contribute to frida/frida development by creating an account on GitHub.

github.com

해당 단말기에 프리다 서버 실행 

 

frida-ps -u  (-u 는 usb로 연결된 단말 기의 프로세스 확인)

 

 

프로세스 실행 
frida -U -f com.TouchEn.mVaccine.DEMO
 - U : usb 로 연결된 디바이스
 - f :  프로세스 실행

 

- 프로그램 실행 후 JS 적용
   : frida -U -f [파일이름] -l [JS] --no-pause

 

 

 

'개발 > Frida' 카테고리의 다른 글

[DIVA2] 1. Local DAta Storage  (0) 2022.09.29
FridaLab  (0) 2021.08.06
[IOS] Fairplay DRM 복호화  (1) 2020.10.08
[Frida_IOS] 앱분석_(1)  (0) 2020.09.28

+ Recent posts