나름 깔끔한 날씨 프로그램인 eWeather HD를 Android P OS까지 문제없이 사용하고 있었습니다.

그런데 Galaxy S9을 최신 Q OS 업그레이드 직후 eWeather HD 실행, 화면이 보이는 동시에 crash가 나고 죽어 버립니다.

 

죽는 위치는 dump 하면 쉽게 확인됩니다.

JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c

from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)

 

crash log 중요 내용은 아래와 같습니다.

02-17 02:25:19.945 10426 13450 16754 F nt.WeatherCloc: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c
02-17 02:25:19.945 10426 13450 16754 F nt.WeatherCloc: java_vm_ext.cc:570]     from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)
...
...
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] Runtime aborting...
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] Dumping all threads without mutator lock held
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] All threads:
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] DALVIK THREADS (17):
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] "AsyncTask #1" prio=4 tid=7 Runnable
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | group="" sCount=0 dsCount=0 flags=0 obj=0x12e5fe20 self=0xd6567800
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | sysTid=16754 nice=10 cgrp=default sched=0/0 handle=0xc3208230
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | state=R schedstat=( 33144883 457271 28 ) utm=1 stm=1 core=5 HZ=100
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | stack=0xc3105000-0xc3107000 stackSize=1040KB
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | held mutexes= "abort lock" "mutator lock"(shared held)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #00 pc 002fe4ef  /apex/com.android.runtime/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+78)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #01 pc 003a768b  /apex/com.android.runtime/lib/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+358)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #02 pc 003a3e63  /apex/com.android.runtime/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+34)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #03 pc 003bc485  /apex/com.android.runtime/lib/libart.so (art::DumpCheckpoint::Run(art::Thread*)+576)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #04 pc 003b70c7  /apex/com.android.runtime/lib/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+354)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #05 pc 003b67ad  /apex/com.android.runtime/lib/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+1416)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #06 pc 00376953  /apex/com.android.runtime/lib/libart.so (art::Runtime::Abort(char const*)+1058)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #07 pc 0000855f  /system/lib/libbase.so (android::base::LogMessage::~LogMessage()+406)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #08 pc 0028806f  /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1194)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #09 pc 00288211  /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbortF(char const*, char const*, ...)+64)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #10 pc 003ac06f  /apex/com.android.runtime/lib/libart.so (art::Thread::DecodeJObject(_jobject*) const+538)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #11 pc 00417905  /apex/com.android.runtime/lib/libart.so (_ZN3artL37JniMethodEndWithReferenceHandleResultEP8_jobjectjPNS_6ThreadE.llvm.5386863320803738609+36)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.ArmManager.ARMPluginMakeChallenge(Native method)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.ArmManager.a(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.f.a(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.f.doInBackground(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at android.os.AsyncTask$3.call(AsyncTask.java:378)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.lang.Thread.run(Thread.java:919)
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] 
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:649] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:649]     from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)
...
...
--------- beginning of crash
02-17 02:25:20.230 10426 13450 16754 F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 16754 (AsyncTask #1), pid 13450 (nt.WeatherClock)
02-17 02:25:20.251  1000  4997  5086 E libprocessgroup: Failed to kill process cgroup uid 10158 pid 13776 in 206ms, 1 processes remain
02-17 02:25:20.279 10426 16786 16786 E crash_dump32: unknown process state: t
02-17 02:25:20.290 10426 16786 16786 I crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstone
02-17 02:25:20.295  1058  4758  4758 I /system/bin/tombstoned: received crash request for pid 16754
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: pcf : 0x1012, 0 ,2 ,0 ,0 ,0 ,2, 5.0.0.0
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: thread id : 2, preenroll_flag : 0, nd cnt : 1, cso : 0, et : 0
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: FPBAuthService, 10979
02-17 02:25:20.296 10426 16786 16786 I crash_dump32: performing dump of process 13450 (target tid = 16754)
02-17 02:25:20.307 10426 16786 16786 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Build fingerprint: 'samsung/starlteks/starlteks:10/QP1A.190711.020/G960NKSU2DTAB:user/release-keys'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Revision: '26'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : ABI: 'arm'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Timestamp: 2020-02-17 02:25:20+0900
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : pid: 13450, tid: 16754, name: AsyncTask #1  >>> com.Elecont.WeatherClock <<<
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : uid: 10426
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Abort message: 'JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c

대충 보면 skt에서 제공하는 so library의 특정 native 함수에서 죽는 문제입니다.

업데이트가 매우 오래전에 멈추어진 App.이라 그럴 수도 있겠죠.

 

핵심 호출 부분은 아래입니다.

at com.skt.arm.f.a(unavailable:-1)

at com.skt.arm.f.doInBackground(unavailable:-1)

 

즉 doInBackground 안에서 호출하는 com.skt.arm.f.a 호출 흐름에서 죽습니다.

이걸 해결할 방법은 없고 대신 호출을 막습니다.

그리고 test하니 - SKT 서비스가 없다면서 App. 을 강제 종료 해 버립니다 우쓰!

 

그래서 doInBackground 종료 후 호출되는 onPostExecute 의 주요 호출을 막으니, 정상 동작이 됩니다.

아마다 예전 SKT 관련 서비스 유무 확인 혹은 여러 내용(라이센?!)을 확인하는 루틴이 Q OS에서 동작이 되지 않은 듯 합니다.

 

어찌 되었건 문제는 해결되었습니다.

비록 오래된 App.이지만 더 이상 update 되지 않는 버전이지만 문제만 해결해서 계속 사용하게 되었습니다.

** 해당 App. 은 Play store에 최신 버전의 App. 이 제공되지만 예전 T Store 와는 다른 signature 사용으로 인해 업그레이드를 할 수 없습니다.

 

주요 수정 point는 아래와 같이 요약할 수 있습니다. 단순히 smali 수준에서 문제 함수를 막아서 해결했습니다.

맨 앞에 # 한 부분입니다.

# virtual methods
.method protected final varargs synthetic doInBackground([Ljava/lang/Object;)Ljava/lang/Object;
    .locals 1

#    invoke-direct {p0}, Lcom/skt/arm/f;->a()Ljava/lang/String;

#    move-result-object v0
	const-string v0, " Not ACTIVITY"

    return-object v0
.end method

.method protected final synthetic onPostExecute(Ljava/lang/Object;)V
    .locals 1

    check-cast p1, Ljava/lang/String;

    invoke-super {p0, p1}, Landroid/os/AsyncTask;->onPostExecute(Ljava/lang/Object;)V

#    iget-object v0, p0, Lcom/skt/arm/f;->a:Lcom/skt/arm/e;

#    invoke-static {v0}, Lcom/skt/arm/e;->a(Lcom/skt/arm/e;)Lcom/skt/arm/ArmManager;

#    move-result-object v0

#    invoke-static {v0}, Lcom/skt/arm/ArmManager;->b(Lcom/skt/arm/ArmManager;)V

    return-void
.end method

위 내용 참고요 스크린 샷 (APK Studio)

APK Studio to fix the crash

* 수정 후 정상 동작 스크린 샷~

 

 

** 리버스 엔지니어링은 더이상 업그레이드가 제공되지 않는 S/W 에 대한 호환성 확보를 위한 목적에는 적법합니다.

컴퓨터프로그램 보호법 - 역분석 관련 법

제12조의2 (프로그램코드역분석)
①정당한 권원에 의하여 프로그램을 사용하는 자 또는 그의 허락을 받은 자가 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우 당해 프로그램의 호환에 필요한 부분에 한하여 프로그램저작권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다.
②제1항의 규정에 의한 프로그램코드역분석을 통하여 얻은 정보는 다음 각호의 1에 해당하는 경우에는 이를 사용할 수 없다.
   1. 호환 목적외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우
   2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 기타의 프로그램저작권을 침해하는 행위에 이용하는 경우
      [본조신설 2001·1·16][[시행일 2001·7·17]]

 

이 글에서는, 미라지(M480, M4800) 320x320 해상도에서 맵피Go를 사용할 수 있는 패치정보를 제공 해 드립니다.

갱신내역
  [2011-01-29] MappyGo v1.0.13A 용 패치 파일 등록




맵피 Go! - 새로운 버전인 맵피가 나온지도 꾀 되었습니다.

저도 개인적으로는 차량용 전용 내비게이션을 사용하고 있는 관계로 M480, M4800용 맵피고가 나옴에도 불구하고 신경을 쓰지 못했습니다.

참고로 차량용 내비로는 파인디지탈 IQ 3D 1000 을 사용 중입니다. 이전에 IQ Blue를 사용하다 한번 더 갈아 탓는데요. Blue도 경품 당첨!, 3D 1000은 물건 구입에 대한 할인개념으로 받은 것이라~ ㅎㅎ
잡설이 길었습니다.


이제는 iPhone, Android phone이 '스마트 폰'의 기본이 되어버린 시대에 미라지(M480, M4800)사용자도 급감하고 있는 것 같더군요.
저 역시 차에서는 전용 내비를 사용중이긴 하나, 휴대폰은 아직도(!) M4800 미라지를 사용 중입니다. 여러 벌레도 많고, 불편한것이 많으나 갤럭시S 사기에는 너무 늦은 시점이라... 갤럭시S 2 나오기 전 까지는 이용 중입니다.
역시나 잘설(2)도 길었네요 ㅎㅎ.


그리하여~ 맵피Go 에 대해서도 미라지에서 사용하기 위해 약간의 연구, 분석을 했습니다.

이전과 완전히 달라진 프로그램인 맵피Go 답게, 이전과는 완전히 다른 방식으로 code가 구성이 되어, 약간의 삽질이 필요 했습니다.
처음에는 너무 급하게, 쉽게 패치 하려다가 엉뚱한데서 돌고 돌았습니다.

하지만 이번에도 2가지 패치를 거쳐서 미라지에서도 맵피Go를 어정쩡 하지만, 답답한 대로 사용 할 수 있게 되었습니다.


이번 맵피Go는 해상도를 96 DPI(강제호환 설정) / 128 DPI(미라지 기본) 설정함에 관계없이 동작은 합니다.
다만 기본 상태에서는 메뉴바가 화면 한가운데를 가로 질러가 버리는 문제가 있고, 이 때 화면 터치시에 가로는 맞으나, 세로가 보는 것과 터치가 다른 문제가 있습니다.
가장 큰 문제는 메뉴바가 사라져 버리고, 이후로 메뉴를 접근할 수 없는 아주 심각한 문제가 발생 합니다.

이 문제의 메뉴바를 아래에 내려 놓으면 좋겠지만....
불행하게도 이전과 같이 GetDeviceCaps 함수는 눈 닦고 봐도 보이지 않습니다.
대신에 화면 해상도에 따른, 화면 구성파일 2개 중 하나를 이용해서 화면을 구성하는 형식이더군요.
파일로는 mappysl240.art 파일 혹은 mappysl320.art 파일이 화면을 구성하는 파일이고, 이 둘중 하나 선택 하는 정도는 프로그램적으로 접근이 가능하나, 이 파일을 분석하는 것은 현재로서는 제 능력 밖인 듯 합니다.

그래서, 쉽고도 간단하게 문제가 되는 320 X 240 인식이 아닌(미라지에서 이렇게 인식 됨), 240 X 320으로 강제 인식하도록 수정하는게 이번 패치의 주된 일입니다.
다만 이로 인해 우측의 남는 부분 (320-240) 80 pixel 만큼의 영역은 최초 배경이 보이는 문제가 있습니다. 이런 현상을 감안 하고 사용 하실 분은 아래 제공 해 드리는 패치 파일로 꺼져가는 미라지에 대한 사랑을 조금이라도 살려 보시길 바랍니다.


관련 힌트 디스어셈블리 코드
.text:0001B4E0                 ADD     R12, SP, #0x420+var_220
.text:0001B4E4                 STRH    R3, [R12,#8]
.text:0001B4E8                 BL      memset
.text:0001B4EC                 LDR     R4, =unk_14DC5C
.text:0001B4F0                 LDR     R1, =aSSMappysl320_a
.text:0001B4F4                 LDR     R3, =aImage
.text:0001B4F8                 LDR     R2, [R4]
.text:0001B4FC                 ADD     R0, SP, #0x420+var_420
.text:0001B500                 ADD     R2, R2, #0x218
.text:0001B504                 BL      swprintf
.text:0001B508                 LDR     R2, [R4]
.text:0001B50C                 LDR     R1, =aSSMappysl240_a
.text:0001B510                 LDR     R3, =aImage
.text:0001B514                 ADD     R2, R2, #0x218
.text:0001B518                 ADD     R0, SP, #0x420+var_218
.text:0001B51C                 BL      swprintf
.text:0001B520                 LDR     R0, [R5,#0x5C]

다만 code를 직접 건드리는 것은 여러 귀찮은 문제가 있으므로, 위 파일명이 저장된 위치에서 "mappySl320.art" 부분을 찾아서 "mappySl240.art" 로 수정 합니다.
아래 위치입니다.

즉 Sl320 으로 된 부분을 걍 Sl240 으로 32 대신 24로 수정 하는 작업 입니다.
이것 만으로, 미라지에서 강제로 240 X 320 해상도로 고정을 해 버리고, 화면이 보기 좋지 않으나, 적어도 실행 중에 메뉴가 사라지는 문제는 없앨 수 있었습니다.

000fe2b0h: 76 00 00 00 25 00 73 00 5C 00 25 00 73 00 5C 00 ; v...%.s.\.%.s.\.
000fe2c0h: 6D 00 61 00 70 00 70 00 79 00 53 00 6C 00 32 00 ; m.a.p.p.y.S.l.2.
000fe2d0h: 34 00 30 00 2E 00 61 00 72 00 74 00 00 00 00 00 ; 4.0...a.r.t.....
000fe2e0h: 49 00 6D 00 61 00 67 00 65 00 00 00 25 00 73 00 ; I.m.a.g.e...%.s.
000fe2f0h: 5C 00 25 00 73 00 5C 00 6D 00 61 00 70 00 70 00 ; \.%.s.\.m.a.p.p.
000fe300h: 79 00 53 00 6C 00 32 00 34 00 30 00 2E 00 61 00 ; y.S.l.2.4.0...a.

위 내용 보시고 직접 patch 하셔도 되구,
아래 파일을 이용해서 패치 하셔도 됩니다.

[안내]
아래 제공되는 파일은 맵피 PDA 라이센스를 소유 하고 있으나 M&Soft 에서 이해할 수 없는 정책을 주장하여M480, M4800 에서는 사용 할 수 없는 호환성을 해결하고자 개인적으로 만든 파일 입니다.
관련 법을 준수하시기 바랍니다.
컴퓨터프로그램 보호법 - 역분석 관련 법

제12조의2 (프로그램코드역분석)
①정당한 권원에 의하여 프로그램을 사용하는 자 또는 그의 허락을 받은 자가 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우 당해 프로그램의 호환에 필요한 부분에 한하여 프로그램저작권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다.
②제1항의 규정에 의한 프로그램코드역분석을 통하여 얻은 정보는 다음 각호의 1에 해당하는 경우에는 이를 사용할 수 없다.
   1. 호환 목적외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우
   2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 기타의 프로그램저작권을 침해하는 행위에 이용하는 경우
      [본조신설 2001·1·16][[시행일 2001·7·17]]

이 파일을 이용해서 맵피를 사용 하기 위해서는 
반드시 맵피 PDA 라이센스를 소유 하고 있으며, 또한 Mappy 전체 이미지를 정상적으로 download하신 분 만이 사용이 가능 합니다.

여기서 안내드리는 내용은 직접 patch를 할 수 있는 정보와 patch용 요약자료만 공유 합니다.
패치 프로그램과 Mappy라이센스, Mappy 인스톨 파일은 개인 소유의 것을 이용하셔야 합니다.


Patch 파일은 Free software인 VPatch 를 사용 했습니다. Google 등의 검색엔진을 이용하셔서 개인이 구하셔야 합니다. 또한 별도 패치용 실행 파일도 제공을 합니다.
이 프로그래과 제공하는 data를 이용하여 발생하는 법적인 문제에 대해서는 사용하는 당사자들의 책임임을 밝혀 둡니다.

아래 파일에 대해서는 그 어떠한 질문에 대해서도 답변을 드리지 않습니다.

패치요약 파일:

[2011-01-29] MappyGo v1.0.13A



위 파일은 VPatch 라는 프로그램을 설치하고난 뒤에 전용 프로그램을 이용하시면 됩니다.

*당연히 PDA(WM5.0)용 맵피Go 1.0.12 (파일 날짜 2010-11-22) 를 소유해야 합니다.
*Patch 실행 법은 VPatch 설명서를 참고 하세요.
>  
VPATCHPROMPT.EXE PatchData_MappyGo_101222_For_M430x (sourcefile) (outputfile)

혹은 아래 실행 파일을 이용하셔도 됩니다.

VPatch_MappyGo_101222_For_M430x (Original) (Output)

그럼 미라지와 함께 즐 맵피Go 하시길 바라며~ 오늘도 이정도로 글을 끝낼까 합니다.
맵피Go가 큰 변동 없다면 한동안 업데이트 할 것 같으나... 저도 미라지를 떠나게 되면 어떻게 될지는 장담 할 수 없을 것 같습니다.

추가로 - GPS 잡은 모습 보여 드립니다.
이전 버전과 달리 자동 탐색하면 제대로 잡아 주고, 사용에도 문제 없는 듯 합니다. 다만 미리 External GPS 데이타는 한번 받아 주세요.




법률 조언을 거쳐서 주요 내용을 수정 반영 했습니다.
향후 법률적 의견은 적법한 절차에 의해서 진행 해 주시기 바랍니다.



Eliminate DRM! by baughj 저작자 표시동일조건 변경허락

법률 조언을 거쳐서 주요 내용을 수정 반영 했습니다.
향후 법률적 의견은 적법한 절차에 의해서 진행 해 주시기 바랍니다.


[참조 링크]
유사 솔루션인 - 웹페이지 보안 관련 참고 사항 
  2011/03/06 [역공]간단하고 깔끔한 - 웹 보안 프로그램 회피방법 (Fiddler-Web Debugging Proxy 활용) 


아래방법을 극복한 궁극의 구멍 뚫기
  2010/04/22 DRM, 보안 솔루션! - API Hooking 을 맹신 말라!




DRM Elimination Crew Suit by GregoryH 저작자 표시비영리동일조건 변경허락



보안을 강조 하는 것은 당연하 이치로 보입니다.
특히나 기업에서의 보안은 그 중요성을 누구나 잘 알고 있다고 봅니다.

그러나 그 '보안' 때문에 업무와 일이 주가 된 것이 아니라 '보안'이 주가 되고, 이 '보안' 아래에 일을 해야만 하는 주객 전도의 세상을 살아야 하는 현실이 되어 버렸습니다.
기업마다 온갖 종류의 보안 솔루션을 갖추고, 혹시나 일을지 모르는 일(?)에 대비를 하고 있는 것으로 보입니다.
문마다 보안장치와 보안요원은 기본이고, 컴퓨터 사용에도 몇중의 솔수션을 설치하고 감시받아야 하는 사항이죠.
외국 회사에 방문 해 보셨습니까? 그들이 한국 회사만큼 중요성을 몰라서 그렇게 하지는 않을 것 같구요.

대부분의 보안 문제는 내부 행위자 한명의 마음 먹기에 달렸더군요.
몇중의 막음과, 솔루션 도입 대신에 사람 마음 잡기가 더 중요할 것 같습니다

저도 평범한 직장인이라 이러한 보안 솔루션에 갇혀서 살아야 하는데, 가장 마음에 들지 않는 것 중 하나(그 중의 하나일 뿐!)가 문서 보안설정이 있습니다.
뭐- 도입 배경 설명은 맞습니다. 혹시나의 유출, 의도적 유출에 대비해서 무조건 적으로 문서에 대해서 DRM을 걸어 버리고 암호화 해 버리면 - 외부에서 해당 문서는 쓰레기 일 뿐이죠.

하지만 내부 사용과 활용에도 기본권(?)을 뺏기고 있는 느낌이라고 할까요?
내부 사용자 끼리 문서가 이리저리 전송되면서 DRM으로 인해 열어 보지도 못하는 경우도 자주 일어나고, 특정 시스템만 사용하는 그런 가슴아픈(?) 문제가 속속 발견 되고 있습니다.

그래서, 개인적으로 답답한 상황에 잠시 사용 할 해결책을 만들었습니다.

쉽게 설명하면,
DRM에 의해 암호화된 파일을 상황에 따라 암호화를 해제하는 것입니다.
중요한 필수 조건으로 해당 파일에 대한 읽기 권한은 있어야 합니다. 읽기조차 불가능한 파일을 해제 하는 방법은 저도 불가능하네요.


아래 내용은 법률자문 결과 적법한 방식대로 설명을 수정했습니다.
또한 더이상 아래 방법으로는 원하는 결과를 얻을 수 없습니다. 참고글로만 남겨 둡니다.

1. 반갑지 않은 손님

어느날 문득! 그분이 오셨습니다. 이름은 ★★! - 오실 필요 없다고했으나, 걍 컴퓨터를 지켜 주신다고 오셨다네요.
그리고 동거가 시작 되었습니다. 이미 같이 살면서 소통을 감시하고 있던 다른 넘과 함께, 시스템 리소스까지 쭉쭉 빼가면서 말이죠.

그러던 ★★께서 이젠 나의 글은 더이상 나의 글이 아니라고, 글을 작성할 때 마다 암호화를 하셨답니다. 그리고 읽을 때에는 ★★님께서 직접 번역해서 돌려 주시는 군요. 혹시나 나의 글이 적들에게 노출 될까 불안해서 그렇답니다.

그런데 이 ★★님께서는 오피스 파일에 대해서만 관심이 많더군요.
오피스에서 작성한 오피스 관련 파일은 모조리 DRM 걸어 주시는 친절함! 눈물을 앞을 가립니다. PDF까지도 잊지 않고 챙겨 주시는 군요.

하지만 이 ★★님에게도 구멍이 있어보였습니다!
오피스 실행 프로그램을 조작하지도 않고도 해당 결과물에 대해서 만능으로 "척척" DRM을 걸었다가 해제 해 주시는 능력! 이것이 구멍인 것이죠.

즉 제가만든 가짜를 오피스라고 속이면 ★★께서 알아서 속아 넘어 갈듯한 느낌으로 일은 시작 되었습니다.



2. ★★를 속이기는 쉬울까?

처음 시작은 메모장(notepad.exe)이었습니다.
DRM파일을 열어보면 DRM 파일임을 밝히는 문자열이 포함되어 있습니다. 이 부분을 보기 쉬운 메모장의을 이용해서 파일명만 Winword.exe(MS 워드)로 변환을 하면 ★★가 '허'하지 않을 까 하구요.

이름만 Winword.exe로 바꾸고 DRM 파일을 열었는데!
헉! - DRM 문자열이 없었습니다. DRM해제된 상태로 open되었다는 것이죠.
UltraEdit에서 열어 보았습니다. DRM상태 그래도 열렸습니다.

즉 제 잔머리가 통한것으로 보였습니다.
★★DRM은 원본 실행 파일을 수정 하는 것이 아니라, 파일열 열고, 읽고, 저장 하는 단계에서 조작을 가하는 것으로 이해 될 수 있습니다.

그래서, 새로 만든 application을 이용해 ★★DRM을 속이고, 저장은 다른 방법 - 왜냐면 파일 저장시에 DRM화 해 버리면 원본을 얻을 수 없기에 - 또 다른 실행 파일로 PIPE 연결을 통해서 별도 프로세스(DRM감시에 포함되지 않는)에서 저장 하려고 계획을 세웠답니다.

그리고 VC++로 메모장을 하나 만들고, 파일명을 위와 같이 Winword.exe로 바꾸었습니다.
별도로 만든 app.에서 DRM파일을 열고, 다른 방식으로 파일을 저장만 하면 되는 것으로 생각해서였죠!

그런데! - DRM해제 되지 않는 것입니다. 걍 DRM 인코딩된 상태로 읽어 버렸네요.

실행 파일 이름 변경만으로 ★★DRM은 속지 않는 다는 것이죠 (제가 ★★를 넘 물로 본것인가요 ㅋ~)



3. ★★는 오피스를 잘 알고 있었다

그제서야 SysInternals의 Dbgview.exe로 디버깅 메시지를 보니!

넵. 그렇네요. ★★는 오피스를 비롯한 메모장을 실시간으로 인식하고 있었습니다.

아래는 Notepad.exe실행시의 debug 출력 내용 입니다.
?????? 은 제가 숨김 처리 했는 내용 입니다. (혹시나 절 잡어러 오실까바? 그런데 뭔 근거로 절 잡나요?)
[0000] API Hook / getCMHLatestMoudelPath --> C:\Program Files\??????\??????.dll
[0000] * [★★Notepad] ================================================================================
[0000] * [★★Notepad] [ C★★e : Version v?.?.?.?                                                  ]
[0000] * [★★Notepad] [ C★★e : ★★ is 'c:\program files\??????\??????\??????.log'       ]
[0000] * [★★Notepad] [ C★★e : ★★el = , U★★ ★★ = 'TRUE'             ]
[0000] * [★★Notepad] --------------------------------------------------------------------------------
[0000] N [★★Notepad] << Ex★★ ★★ - ??????.dll : ★★on ★★ - v?.?.?.? >>
[0000] N [★★Notepad] --------------------------------------------------------------------------------
[0000]
[0000] D [★★Notepad] [★★] DATATYPE_★★_★★_COPYPASTE

다른 오피스 실행 파일 (워드, 엑셀, 파워포인트 등등)도 유사 log가 출력됩니다.
이 내용은 ★★DRM이 특정 실행 파일에 대해서 DRM 처리에 대한 판단을 하고, 통제를 한다는 의미가 되겠습니다.

그렇다면 앞서 파일명만 바꾸어서는 아니고, 오피스 실행파일로 완전히 속여야만 한다는 것인데요. ★★의 정신세계에 들어 가기 위해서는 리버스엔지니어링 - 즉 '역공'을 해야 하는데, 귀찮기도 하고 혹시나 법으로 밀어 부치면 어쩔 도리가 없으니...

쉬운 방법을 생각 해 냈습니다.



4. 오피스에 숨어 들어가기

★★ 덕분에 오피스에서 출력 해 내는 아크로벳(PDF) 파일도 DRM에 걸려 버리더군요.
★★는 특정 application의 파일 조작에 대해서 철저하게 동작을 달리 한다고 할 수 있는 단서이기도 합니다.
다시 요약하면 API hooking 혹은 hijacking 이라는 기술을 사용 하는 것이죠.

몇몇 감시 프로그램에서 행하는 공통 행동으로 유추하면, Windows API인, CreateFile, ReadFile, WriteFile 에 대해서 일일이 호작질(?)을 하여 오피스 등의 실행 파일의 경우에 대해서 현재 컴퓨터의 DRM 정책에 따라 열고, 읽고, 쓰기 시점에 적절히 DRM 동작을 수행 하는 것이죠.

자! 여기서 새로운 아이디어를 내어 봅니다.
최초 목적이 특정 파일에 대해서 DRM해제를 하고자 했습니다. 다시 말해 원래부터 제가 직접 작성한 문서 혹은 제가 읽을 수 있는 문서를 DRM 해제 하는 것이였으므로, 해당 문서에 대해서 제가 최소한 열어볼 수는 있다는 것입니다.
열어 볼수가 있다는 말은 파일이 오피스프로그램에 의해서는 DRM 해제가 된다는 것으로 해석이 됩니다.
아래의 과정이 일어 나는 것이죠.

    DRM 인코딩된 문서 파일 --> ★★DRM 모듈 --> 오피스실행파일

읽기 권한만 있어도 결국 DRM 인코딩된 문서 파일이 파일 Open, Read 시점에는 DRM해제가 되어야 한다는 것도 당연한 과정입니다. 오피스는 열고 있는 파일이 당연히 자신의 포맷으로 작성된 파일이 아니라 DRM 인코딩된 파일을 스스로 해결을 못하기 때문이죠 (이것이 핵심적인 구멍 입니다)

오피스 자체적으로 읽어 들인 파일에 대해서는 DRM해제가 투명하게 이루어 진다는 것으로 해석이 됩니다.

만일 오피스 스크립트 언어인 - VBA(Visual Basic for Application) 실행을 통한 파일 Open, Read에 대해서는 어떻게 될까?
만일 VBA 내에서 파일을 열고, 읽은 파일이 DRM해제가 된다면! - 절반은 성공 한 것이죠.

실험 해 보았습니다. - 단 VBA 자체적인 파일 read는 제약이 있기에 별도의 Win API 어댑터를 통했습니다.
1. 대화상자로 파일 선택
2. 선택한 파일을 버퍼로 읽기
3. 버퍼로 읽은 파일 내용을 출력 하기


3번 과정에서 만일 아래와 같은 문자열이 발견 되었다면, DRM파일 읽기 실패(혹은 권한 없는 파일) 입니다.
<!--★★★★★★★★★★★★★★★★ -->
혹은 사용 환경에 따라 유사한 다른 text가 될 수 있습니다.
일반 text 뷰어로도 확인이 가능 합니다.

그런데! - 위와 다른 내용을 얻었습니다.
넵! 정리하면 아래와 같습니다.

Office에서 VBA로 만든 실행 코드에서 DRM 파일을 Open하게 되면(권한이 있을 경우),
당연히 DRM해제 동작이 일어나게 되어 Read한 내용은 DRM 처리 되지 않은 원본 내용을 얻을 수가 있다!



5. 원본 파일을 얻다!

Office VBA에서 파일을 열고, Read 하면 DRM 해제가 된 원본 파일 스트림을 얻게 된다는 것 까지 확인을 했습니다.
그러면, 읽은 스트림을 바로 파일로 저장하면 어떻게 될까요?

앞서 별도로 test한 사항이 있습니다.
Office에서 다른이름으로 저장을 해 봤습니다.
당연히 확장자가 다르면 어떻게 될지 여부의 실험이었죠! - 혹시나 했는데 ㅎㅎㅎ
강제로 확장자를 붙여 줘 버립니다! 놀랍군요! - Office 에서는 이런 친절을 배푼적은 없습니다. 바로 ★★님의 '호작질' 중에 하나라는 것이죠.

여기서 중요한 단서가 하나더 나왔습니다! 두둥!
★★님의 DRM화 저장은 결국 파일의 확장자가 중요한 판단 기준으로 작용 한다 입니다!
여기서 아픔이 느껴지는 군요! - 이렇게 할 수 밖에 없는 이유는 충분히 공감이 갑니다.

Office도 인간이 아닌 컴퓨터 실행 파일이고 결과 파일만 저장 하는 것이 아니라 각종 설정 파일 저장은 물론이고 Win 표준 API인 CreateFile(기존 파일 열기에도 이것 사용합니다), ReadFile, WriteFile을 광범위 하게 사용 할 것이라는 것입니다.
당연히 위 API는 파일 I/O 뿐만 아니라 여러 스트림 입/출력에도 공통적으로 사용하게 되므로 모든 동작에 대해서 DRM을 걸어 버리면 - 결과적으로 Office가 바보가 되어 버리는 큰일이 벌어질 것이라는 겁니다.

그래서 아픔은 있으나, 타협안으로 Office 파일에 대한 확장자를 눈이 뚫어지라 지켜 보다가, 해당 파일만 DRM 인코딩, 디코딩을 해 주는 것으로 결론을 낸 것 같습니다.

그래서! 앞서 VBA로 열고, 버퍼로 읽어들인 파일을 - 곧바로 저장하지 않고, 확장자만 변경을 했습니다.
예로서 .xls 라면 .xls_unpacked 식으로 말이죠!

결과는!!!!!! - 예상대로(너무나 허무하게?) DRM에 걸리지 않은 파일을 얻게 되었습니다.
사실 설명은 길었습니다만... 간단하게 정리하면 아래와 같습니다.

★★ DRM은
-파일 Create, Read, Write 시점에 DRM 인코딩, 디코딩을 행한다.
-오피스 실행 파일을 알아 차리고 DRM 과정을 행한다. (듣보잡 실행파일은 DRM파일 읽기 불가)
-허용된 실행파일에서 파일 읽기 과정에서 확장자 기준으로 DRM파일이면 DRM해제 과정을 행한다
-DRM해제 과정은 VBA로 만들어진 code(오피스 파일 Read) 에서도 유효하다
-파일 Write 과정에서 확장자가 DRM 대상이 아니라면 DRM 인코딩 과정은 일어나지 않는다.




6. ★★의 구멍!

DRM해제된 파일을 성공적으로 변환 하고서, 궁금증으로 ★★(www.★★.com)을 방문 해 보았습니다.
소개된 기술 문서를 보니, 앞서 제가 일일이 잔머리 굴렸던 내용에 대해서 답안을 떡 하니 제시 해 놓았네요!

★★ DRM은 API-Hooking(나쁜 말로 Hijacking)을 사용
그리고, API-Hooking방식이 다른 방식에 비교해서 1등으로 좋음(정말로? 진짜로? 참말로? 에이 설마!)
그리고서는 File system filter 방식보다 보안성이 좋다고 이야기를 하네요!

허허!. 제가 보기에는 File system filter 방식이 더 보안성이 좋다고 보입니다 (저의 생각일 뿐이지만)

위에 설명드린 내용은, 아주 passive하게 역공한 것으로 ★★DRM은 건드리지도 않았습니다. 그래서 구멍 찾기가 맞는 표현이고 역공(Reverse engineering)은 아니라고 할 수 있습니다.
하지만 API hooking 방식은 결과적으로 재 hooking동작과 더불어 해당 모듈에 대한 hooking handler 코드에 대한 patch 동작으로 DRM화 동작을 무력화 할 수도 있습니다.
그래서, 제 입장에서는 File syste filter 방식보다도 좀더 손쉽게 접근 가능해 보입니다.

어느 방식이든 구멍이 없는 것은 아니지만...





이글은 마무리 하고, 실제 DRM해제 파일 얻기위한 code는 추가 글로 올립니다.
계속 즐 DRM 되길 바라며~





휴가와 여러 일로 인해 늦게 5.7.1 버전에 대한 320x320 사용을 위한 수정 내용을 올려 드립니다.
패치 방식은 이전과 동일 합니다. 다만 편의를 위해 패치을 해 주는 독립 실행 파일도 첨부 했습니다.
즐 맵피 하세요~




상세 분석은 이전글을 참고 해 주세요





"차례" "Code address" "파일offset"
     [ 원본 hex code ]  --> [ 수정 hex code ]

320x240 강제 설정 패치 부분

1  0004AC80 ( 03A080 )
   [ F4 A7 07 EB ] --> [ 05 0D A0 E3 ]

2  0004AC90 (
03A090 )
   [ F0 A7 07 EB ] --> [ F0 00 A0 E3 ]

3  000CFCC4 ( 0BF0C4 )
   [ E3 93 05 EB ] --> [ 05 0D A0 E3 ]

4  000CFCD0 ( 0BF0D0 )
   [ E0 93 05 EB ] --> [ F0 00 A0 E3 ]

5  000DC624 ( 0CBA24 )
   [ 8B 61 05 EB ] --> [ 05 0D A0 E3 ]

6  000DC634 ( 0CBA34 )
   [ 87 61 05 EB ] --> [ F0 00 A0 E3 ]

7  000DD75C ( 0CCB5C )
   [ 3D 5D 05 EB ] --> [ 05 0D A0 E3 ]

8  000DD76C ( 0CCB6C )
   [ 39 5D 05 EB ] --> [ F0 00 A0 E3 ]



화면 크기 변동 방지
9    00028F10  ( 018310 )  <
GPS정보 dialog 제대로 보이게 패치: MoveWindow 무효화>
   [ 47 2F 08 EB ] --> [ 00 00 80 E3 ]

10  0004C520  ( 03B920 )  <GPS 인식 직후 화면 제대로 보이게 패치>
   [ C3 A1 07 EB ] --> [ 00 00 80 E3 ]

[안내]
아래 제공되는 파일은 맵피 PDA 라이센스를 소유 하고 있으나 M&Soft 에서 이해할 수 없는 정책을 주장하여 M480, M4800 에서는 사용 할 수 없는 호환성을 해결하고자 개인적으로 만든 파일 입니다.
관련 법을 준수하시기 바랍니다.
컴퓨터프로그램 보호법 - 역분석 관련 법

제12조의2 (프로그램코드역분석)
①정당한 권원에 의하여 프로그램을 사용하는 자 또는 그의 허락을 받은 자가 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우 당해 프로그램의 호환에 필요한 부분에 한하여 프로그램저작권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다.
②제1항의 규정에 의한 프로그램코드역분석을 통하여 얻은 정보는 다음 각호의 1에 해당하는 경우에는 이를 사용할 수 없다.
   1. 호환 목적외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우
   2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 기타의 프로그램저작권을 침해하는 행위에 이용하는 경우
      [본조신설 2001·1·16][[시행일 2001·7·17]]

이 파일을 이용해서 맵피를 사용 하기 위해서는
반드시 맵피 PDA 라이센스를 소유 하고 있으며, 또한 Mappy 전체 이미지를 정상적으로 download하신 분 만이 사용이 가능 합니다.

여기서 안내드리는 내용은 직접 patch를 할 수 있는 정보와 patch용 요약자료만 공유 합니다.
패치 프로그램과 Mappy라이센스, Mappy 인스톨 파일은 개인 소유의 것을 이용하셔야 합니다.


Patch 파일은 Free software인 VPatch 를 사용 했습니다. Google 등의 검색엔진을 이용하셔서 개인이 구하셔야 합니다.
이 프로그래과 제공하는 data를 이용하여 발생하는 법적인 문제에 대해서는 사용하는 당사자들의 책임임을 밝혀 둡니다.

아래 파일에 대해서는 그 어떠한 질문에 대해서도 답변을 드리지 않습니다.

패치요약 파일:



위 파일은 VPatch 라는 프로그램을 설치하고난 뒤에 전용 프로그램을 이용하시면 됩니다.

*당연히 PDA용 Mappy 5.7.1 버전 원본이 있어야 합니다.
*Patch 실행 법은 VPatch 설명서를 참고 하세요.
VPATCHPROMPT.EXE Mappy5.7.1_090806_M480x_320x240.pat (sourcefile) (outputfile)

혹은 아래 실행 파일을 이용하셔도 됩니다.

> Mappy5.7.1_090806_M480x_320x240 (Original) (Output)

+ Recent posts