넥슨 해킹 확인 방법을 알려드립니다.
아주 간단하긴 하지만, 이런 가이드가 있으면 편하실 것 같아서 정리차원에서 드려봅니다. 탈퇴 프로세스가 번거로웠습니다.

 

본인 계정으로 해킹된 계정이 넥슨 메이플 스토리에 등록되어 있으면, 탈퇴를 할 수 없습니다.

(https://user.nexon.com/mypage/page/nx.aspx?url=myinfomanage/secede)

 

 

 

탈퇴를 진행하면 다음의 화면이 나오면서 탈퇴를 할 수 없다고 나옵니다. 그리고 게임 탈퇴를 클릭하면 메이플 스토리 웹만 뜹니다.

 

 

 
 

저의 계정은 해킹되어서 메이플 스토리 4개 계정이 만들어졌으며, 프로파일까지 변경되어 있었습니다.

 

1. 넥슨 회원인지 확인

넥슨에 가입하지 않았지만 가입되어 있는 상황이 있을 수 있습니다. 먼저 넥슨 (http://www.nexon.com) 홈페이지에 접근합니다.  상단 좌측에 있는 로그인 창 밑에 있는 아이디 찾기를 선택해서 넥슨 회원으로 가입되어 있는지 확인합니다.  

 

 

2. 넥슨 회원에 가입되어 있으면  비밀번호를 찾으시거나, 기존의 비밀번호를 넣으시면 로그인을 확인할 수 있습니다. 아이디와 패스워드를 잘 기억해주세요.

 

3. 메이플 스토리 홈페이지(http://maplestory.nexon.com/) 에서 해킹되었는지 확인합니다.

메이플 스토리 홈페이지의 로그인은 새로운 계정이 필요로 하는 곳입니다. 따라서 다시 id/pw 찾기를 합니다.  

 

주민번호인증/아이핀 인증 팝업창이 뜨면, 편하신 인증방법을 선택합니다.

 

 

 

 

넥슨의 아이디, 비밀번호, 이름, 주민번호를 넣어야 메이플 스토리 계정을 알 수 있습니다. 넥슨 일반 게임과 달리 인증 방식을 취하고 있습니다.

 

 

 하하 4개나 털렸습니다.

  

 

 

마지막 두자리를 **으로 숨겨서 메이플 스토리 계정을 알 수 없도록 되어 있습니다.

그래서 전화를 통해서 탈퇴를 해야 합니다.

 

3. 탈퇴 신청

메이플 스토리 계정을 모르는 상태에서는 오직 전화를 이용해야 합니다. 메이플 스토리 계정을 모르는 한 할 수 있는 것이 없습니다.  만약 메이플 스토리 계정을 안다면, 모든 계정에 대해서 탈퇴를 진행하고 넥슨 계정 탈퇴를 하시면 됩니다.

저의 경우는 메이플 스토리 계정을 모르기 때문에 전화로 탈퇴를 신청했습니다.

넥슨 고객 센터 전화번호는 1588-5509 번입니다. 그다음 주민 번호를 넣으시고, 2번 눌러주시고 상담원과 통화해서 탈퇴를 진행하면 됩니다. 개인인지 확인하기 위해서 주민등록증이나 운전면허 번호로 인증하는 것이 있습니다.

해킹때문에 사람들이 많이 전화 통화를 하는 것 같습니다.
통화 시도는 10차례 이상 시도했으며, 탈퇴신청을 했고, 문자로 탈퇴 결과 알려준다고 합니다.

Posted by '김용환'
,

다음과 같은 Exception이 발생했다.
cubrid.jdbc.driver.CUBRIDException
Has been interrupted.
 at cubrid.jdbc.driver.CUBRIDStatement.checkExecuteError(CUBRIDStatement.java:909)
 at cubrid.jdbc.driver.CUBRIDStatement.executeCoreInternal(CUBRIDStatement.java:802)
 at cubrid.jdbc.driver.CUBRIDStatement.executeCore(CUBRIDStatement.java:769)
 at cubrid.jdbc.driver.CUBRIDPreparedStatement.execute(CUBRIDPreparedStatement.java:453)
 at core.log.impl.PreparedStatementLoggable.execute(PreparedStatementLoggable.java:109)
 at sun.reflect.GeneratedMethodAccessor30.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at core.log.aop.handler.DaoInfo.doAround(DaoInfo.java:95)
 at core.log.aop.reflection.profiler.AroundProfiler.invoke(AroundProfiler.java:19)
 at $Proxy3.execute(Unknown Source)
 at sun.reflect.GeneratedMethodAccessor30.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at com.ibatis.common.jdbc.logging.PreparedStatementLogProxy.invoke(PreparedStatementLogProxy.java:62)
 at $Proxy4.execute(Unknown Source)
 at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:182)
 at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:205)
 at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:173)
 at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:104)
 at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:565)
 at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:540)
 at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
 at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:84)


원인은 timeout과 관련된 것으로서, PreparedStatement.setQueryTimeout 으로 지정한 시간보다 긴 Query 실행시 나타날 수 있는 Exception이다. timeout을 길게 해주면 된다.
Posted by '김용환'
,

4개의 레고 마인드스톰 nxt을 이용해서 큐브 조립를 5.15초에 해결




2010년도에 만든 것. 9초 정도 소요되었음

Posted by '김용환'
,

넥슨 해킹..

scribbling 2011. 11. 25. 22:18


1,300만명의 계정이 털렸다는 뉴스가 떴다.

http://search.naver.com/search.naver?where=nexearch&sm=tol_hty&query=%B3%D8%BD%BC+%C7%D8%C5%B7


내 생각에는 기본적으로 보안을 잘 지키지 못하는 회사는 비전이 없는 것 같다.
일본에 상장하는 것보다 더 중요한 것은 기본을 지키는 것인데, 많이 실망했다.

네슨 계정은 해킹되어서 별명, 다양한 캐릭터가 만들어져 있어서 탈퇴를 하려고 했다.
암호화된 비밀번호도 뚫렸다고 했지만, 내 해킹된 계정의 프로필은 이미 낙서가 되어 있는거 봐서는 패스워드는 완전히 떨렸다고 생각이 된다. 만약 암호화된 패스워드가 뚫렸다면, 이미 보안 암고리즘까지 알고 있다는 것 같다.

근데, 탈퇴는 왜 이렇게 힘들게 만들었니? 아무리 게임회사지만, 탈퇴처리가 어렵게 해서 탈퇴를 포기하게 하지 않아주면 좋겠다.

http://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&ie=utf8&query=%EB%84%A5%EC%8A%A8+%ED%83%88%ED%87%B4

이 사건을 통해서 좋은 회사인 넥슨이 다시 서비스를 고민하는 때가 되기를 바래.




곰곰히 생각해보니 내가 회사에서 처리했던 업무 중에 보안 공격에 대비하는 사례들을 정리해 본다.

1. 게임서버, .net, IIS 서버를 기반으로하는 윈도우 서버는 아예 쓰지 않도록 한다.
윈도우 서버는 워낙 잘 업데이트하지 않으면 자주 취약점이 자주 발생된다. 따라서 그 취약점으로 공격한다.
내 생각에는 모든 것을 리눅스 서버에서 관리하는 것이 가장 좋은 것 같다.  리눅스의 장점이 크다.
다만 윈도우 개발자가 MSSQL과 MS 제품군을 개발환경이 뛰어나 다른 대체재를 찾을 수 없다는 점. 리눅스를 너무 어려워하는 것이 가장 큰 난제..

대부분의 해킹은 윈도우 서버로 접속하는 경우에서 발생되는 경우인 것을 많이 봐왔기 때문에 윈도우 서버만 보면 리눅스로 바꾸고 싶다.
내가 담당자라면 리눅스-자바,C++로 바꾼다.


2. 윈도우 서버에 접근 하는 계정과 윈도우 서버를 잘 관리한다.
학원에서 알려준 아이디/패스워드를 admin/admin 계정을 회사에서도 사용하는 인프라 운영자가 은근히 있다. 내가 다는 회사에서도 이런 사람들 있다. ㅡ.ㅡ;;;;
admin/passwd 이렇게 쓰는 사람도 있었다.
패스워드는 무조건 3개월에 한번씩 바꾼다. 

윈도우 서버를 몇대나 관리하는지, 항상 신경써야 한다.

그리고, 쓸데 없는 정보는 서버에 두지 않는다. 소스같은 것을 두는 사람들이 있었다. 약간 배포 개념이 없는 개발자들이 상당히 많은데, 빌드/배포서버는 따로 두고, 게임/웹 서버는 바이너리만 들어가게 한다.
빌드/배포 서버는 소수의 사람만 접근하도록 하고, 웹 접근만 가능하게 한다.

3, 어드민 계정 관리가 필요하다. 커보러스를 사용하도록 한다.
윈도우 어드민 계정은 정말 잘 관리해야 한다. 아무한테나 패스워드를 알려주지 않는다.
리눅스의 경우는 ssh 대신 커보로스 기반으로 계정관리를 하도록 한다.
ssh로 서버 관리를 하는데, 수천대의 root 비밀번호가 동일하게 하는 인프라 운영자가 있었다.
내가 이거 보안 문제가 심각해질 것이라 하며 바꾸는 것이 좋겟다고 하니, 불편해 함. 한번 구축된 인프라는 바꾸기 어려운 부분이 있음. 처음 설계부터 고민을 많이 하는 게 보안 요소와 개발 요소를 모두 볼 수 있는 개발자가 객관적으로 보고 구축하는게 좋음.
커보러스는 티켓 기반이라 계정 관리가 편한 부분이 있어 요즘 버전은 많이 쓸만해졌다.


4. 개발자의 어드민 계정 선호 사상이 없어야 한다.
일부 개발자는 어드민 계정만 선호하는데, 내가 봤을 때는 잘 못된 생각이다. 개발자는 개발자 계정만 이용해도 된다. 특정 서버로만 어드민 계정 사용하면 된다. 
root는 외부에서 무조건 접근안되게 하며, sudo 권한도 안되게 하면 된다. 필요할 때는 그 때마다 인프라 운영자의 도움을 받아 처리하면 된다.


5. 철저히 ACL 관리를 한다. 또는 방화벽을 잘 써라 
인프라 운영자 또는 보안 담당자는 ACL 목록을 잘 관리하고 있어야 한다. 이거 잘하는 인프라 운영자/보안 담당자를 본 적이 없다. 그냥 승인만 할 뿐, 어떻게 서비스가 동작하는지 전혀 관심이 없어서 관리를 하지 않아, 개발팀에서 서버에 대한 모든 ACL 관리를 하여 서비스 또는 보안에 문제가 없도록 한다. 
 
인프라 운영자와 보안 담당자는 불편하지더라도 ACL 관리를 철저히 함으로서, tcp, udp 포트 뚫을 때마다 인증절차를 거치면서 하는게 좋다. 

방화벽이 없다면, IDC에서는 서로 침투할 수 있는 취약점이 있다. 항상 고민해야 한다.

6.  게임서버는 외부에 ip를 오픈하지 않는다.
L4(L7) 장비 또는 소프트웨어 gateway 를 proxy로 써서, 클라이언트가 direct로 게임서버에 붙지 않도록 한다. 진짜 서버는 안보이게 숨긴다.

7. 쿠키는 항상 안전하게 관리한다.
쿠키 서비스를 할 경우, 쿠키 암호와 암고리즘 또는 쿠키 암호화 알고리즘의 키는 주기적(3개월에 한번)으로 바꾸어 서비스가 튼튼하게 한다. 쿠키 정보를 바탕으로 웹과 게임서버도 통신하기 때문에 쿠키 정보가 외부에서 알지 못하게 해야 한다.
그래서 쿠키를 안전하게 하기 위해서 쿠키+세션 서비스 서버를 구축하는 것도 좋다.

8. 웹/게임 서버에서 DB 접속하는 것은 알고리즘화한다.
개발자들이 많이 취약한 것 중 하나가 db 접속하는 property는 그대로 사용한다는 점이다. 따라서 db 정보, 계정, 암호가 그대로 들어나게 쓰는 개발자가 너무 많다. property를 암호화해서 잘 사용하도록 한다.

9. 회사에서는 아무거나 프로그램을 설치해서 사용하지 않는다.
회사에서 허가된 소프트웨어만 설치하고 사용할 것. 이상한 게임이나 회사에서 쓰지 말라고 하는 것은 쓰지 말아야 한다. 네이트온 해킹 사건도 보면, 회사에서 사용하지 말아야 할 소프트웨어를 쓴 것이라 할 수 있겠다..

10. db 패스워드는 자주 변경한다.
db 패스워드는 주기적(3개월에 한번)으로 변경한다. 불편함보다 보안을 더 중요히 여기자.

11. 서버 데몬 / 라이브러리 모니터링을 잘 한다.
표준화된 서버와 데몬은 정해져 있다. 쓸데 없는 데몬이 있으면 찾아내서 원인 파악을 잘하게 한다. 백도어 데몬은 항상 무섭다.
또한 보안 취약성이 있는 데몬, 라이브러리에 대해서는 빠른 대응이 있도록, 서버의 모든 파일을 검사해서 문제가 되는 데몬, 라이브러리를 파악하고 담당자에게 메일을 보내게 해서 고칠 수 있도록 한다.
오픈 소스 거버넌스와 잘 취합되는 것이 좋다.

12. 서버 로그 모니터링은 좋다.
  access / error 로그를 자주 모니터링한다. 메시지 파일/에러 로그/액세스 로그를 매일 살펴보고 항상 긴장감을 놓치 않는다. 거기서 통찰력이 나온다.

13. 관리자의 마인드 변화
성과도 중요하지만, 보안도 중요하게 여기는 관리자의 마인드가 필요하다. 자기 직원이 잘못한게 있으면 따뜻하게 지적하고 수정하게 하면 된다. 그냥 넘어가지 않게 하고 계속 기본을 지키게 해야 한다.
좋은 지적을 하는 개발자, 운영자의 의견을 잘 듣도록 해야 한다. 자기 부서의 소관이 아니라고 한눈 팔고 있지 말자. 남의 문제를 내 문제로 여길 줄 아는 관리자의 마인드가 필요하다. 타산지석!

12. 시니컬하고 귀찮아하는 운영자보다 회사를 귀하게 여기는 직원을 볼 줄 알아야 한다.
소프트웨어 분야는 뛰어난 한 사람이 대충 일하는 천명보다 백배 귀하다. 항상 겸손하게 문제나 이슈에 대해서 깊이 고민하고 해결할 수 있는 사람을 볼 줄 알아야 한다. 다. 회사의 자원을 마치 자기가 가진 자원처럼 생각하는 사람이 가끔씩 있다. 그 사람이 회사를 성장시킬 수 있다. 사장 마인드로 회사를 보는 직원은 정말 귀하다.

13. 실패을 용인하고 정직한 사람을 귀하게 여기자.
실패를 두려워 해서 거짓말을 하는 사람이 있다. 그것은 아마도 조직문화가 그렇게 만들었을 가능성이 높다. 실패가 용인되지 않는다면 서로 일을 하려 하지 않는다. 실패를 용인하고 그럴 수 있겠다 하며 배울 수 있게 해야 한다. 자신이 실수한 부분에 대해서 책임지려 하는 모습은 아름답다. 누구나 실수를 할 수 있으며 누구나 정직할 수 있는 조직문화가 되어야 다시는 보안문제가 터지지 않도록 잘 마무리 짓고, 열심히 일할 수 있는 분위기가 있어야 한다. 외양간에서 소를 잃지 않도록 예방하는 것도 좋지만, 누가 그렇게 잘 할 수 있겠나..

Posted by '김용환'
,

리눅스 커널 영역에서는 사용자 메모리 공간을 포인터를 이용해서 메모리를 바로 사용할 수 없다.
따라서 복사해야 한다.

유저영역의 메모리를 커널로 복사하는 함수는 copy_from_user 이다.

이런 불편함때문에 생긴게 mmap 이다.  어플이 메모리를 커널에 바로 메모리를 (zero copy) 잡는다.



안드로이드 ipc에는 이런 코드들이 있다. 
binder_wirte_read struct를 을 복사할 때는 copy_from_user, get_user 함수를 이용한다.

transport 하는 데이터는 mmap 으로 관리하도록 되어 있다.
binder_mmap 함수가 바로 그것..

그 안에 binder_update_page_range 함수를 호출하여 물리메모리와 커널의 가상메모리의 수신버퍼, 사용자 공간의 수신버퍼를 매핑한다.

Posted by '김용환'
,
Posted by '김용환'
,



안드로이드 소스





* intent 사용예제

// 1. 어떤 이름인지 모를 때. (클래스 이름을 모를때)
// 필터를 줄 수 있다. 서버의 manifest.xml의 service -> intent-filter -> action에 넣어야 한다. 
Intent i = new Intent("com.google.p.server.REMOTE_SERVICE");

// 2. 클래스 이름을 알고 있을 때.
//             Intent i = new Intent(IMyService.class.getName());



* bind


생명주기













  이미지 출처 
     http://shadowxx.egloos.com/10726222
    http://blog.naver.com/mirnae/100101468187




* aidl

http://developer.android.com/guide/developing/tools/aidl.html

aidl 매니저가  aidl 파일을 일고 stub 코드를 알아서 생성
client가 쓸 수 있는 proxy 코드와 server가 쓸 수 있는  stub 코드를 생성한다.


package com.google.p.server;

interface IMyService {
 int getStatus();
}




=> gen 디렉토리 밑에 자동으로 파일을 생성되어 있다.


/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\AndroidP\\eclipse\\workspaces\\RemoteServerClient\\src\\com\\google\\p\\server\\IMyService.aidl
 */
package com.google.p.server;
public interface IMyService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.google.p.server.IMyService
{
private static final java.lang.String DESCRIPTOR = "com.google.p.server.IMyService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.google.p.server.IMyService interface,
 * generating a proxy if needed.
 */

public static com.google.p.server.IMyService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.google.p.server.IMyService))) {
return ((com.google.p.server.IMyService)iin);
}
return new com.google.p.server.IMyService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getStatus:
{
data.enforceInterface(DESCRIPTOR);
int _result = this.getStatus();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.google.p.server.IMyService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
public int getStatus() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getStatus, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int getStatus() throws android.os.RemoteException;
}





* manifest.xml 

 service에 remote 설정하고 프로세스 단위의 통신이 된다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.google.p.client"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AIDLClient"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.google.p.server.MyService" android:process=":remote" >
            <intent-filter>
                <action android:name="com.google.p.server.REMOTE_SERVICE"></action>
            </intent-filter>
        </service>

    </application>
</manifest>




어플을 올리고, bind 가 되게 한 후(start binding),
 DDMS로 확인하니. 아래와 같이 remote 프로세스가 뜨는지 확인


adb shell로 들어가서, proc 정보를 본다.



어느 파일들을 읽고 있나 본다.
app_process 프로세스와 binder , dalvk 관련 내용들이  보인다.



결국 이런 개념이 됨
 remoteservice.jpg


(이미지 출처 : http://liveeasily.dothome.co.kr/wiki/doku.php?id=android_service)



---------------------------------

인사이드 안드로이드 의 8장 안드로이드 서비스 프레임워크
(네이티브) 샘플 소스를 보드에 넣어보고 테스트해 보기


HelloWorld 시스템 소스



1. 복사를 먼저 한다. 
1)  include 파일은 소스디렉토리\frameworks\base\include 에 include에  복사
2) libs 파일은 소스디렉토리\\frameworks\base\libs 에 libs 에 복사
3) helloworld client 소스는 소스디렉토리\\frameworks\base\helloworld 에 복사

2. 다음은 전체 컴파일을 한다.  

소스디렉토리 # ./build_android.sh 

3. output이 정상적으로 나왔는지 확인
소스디렉토리\out\target\product\sv210\system\lib 밑에 보면,libhelloworld.so 파일이 들어가 있다.


서비스와 클라이언트 파일이 정상적으로 만들어졌는지 본다.

 

4. 이미지 복사
소스빌드디렉토리에서 (out\target\product\sv210)  root.img, system.img 파일을 복사하여 이미지를 다운받기 좋은 곳으로 보낸다.
기존에 있던 bootloader  zImage 파일도 복사해 둔다.


5. 이미지 다운로드
Hybus 보드에 그 이미지를 넣는다.  odin 같은거 없고, 벤더에서 준 ndw.exe 라는 파일을 이용한다.
드라이버 설치하고 나서, 내 컴의 ndw.exe 를 실행한다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


6. adb shell로 명령어를 통해 디바이스로 접근하고 실행해 본다.

# cd /system/bin
# ./helloworldservide &
# ./helloworldclient
hello, world




--------------------------------------------------

안드로이스 시스템 서비스 예제

vender 디렉토리에 넣고, 그 부분만 컴파일 하기

소스



zip을 풀고, 소스 디렉토리\external 아래로 복사하고 빌드한다.
hybus의 기계이름은 HyBus_sv210이다.

# .  build/envsetup.sh
# chooseproduct  HyBus_sv210
# mmm  external/ExService3

make 파일처럼 out\target\product\sv210\system\lib 디렉토리에 libSQRS03.so이 나왔다.

(vender depedent)
4. Hybus 에서는 yaffs로 system  이미지를 바꿔야 한다. system.img를 yaffs 파일시스템 형식으로 변환

소스디렉토리/vendor# ./mkyaffs2image  /work/android_froyo_sv210/out/target/product/sv210/system system.img
system 디렉토리를 yaffs 파일시스템형식으로 img 파일을 복사한다.

(원형    # vendor/mkyaffs2image  system  system.img )


4. 빌드 결과 이미지를 타깃 시스템에 올린다.

1) nand init
nand scrub
nand erase 80000 FF80000

2) kernel write
nand erase 600000 500000
dnw c0008000
[내 컴의 ndw.exe] Select USB Port -> Transmit -> Transmit -> Select zImage
nand write c0008000 600000 500000

3) root.img write
nand erase b00000 500000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select root.img
nand write.yaffs 40000000 b00000 <byte size of system.img>

4) system.img write
nand erase 1000000 5a00000
dnw 40000000
[내 컴의 ndw.exe]  Select USB Port -> Transmit -> Transmit -> Select system.img
nand write.yaffs 40000000 1000000  <byte size of system.img>

5) reset
(Hybus를 재시작한다.)


5. 결과 확인
#adb shell로 접근한다.

 


6. server 실행하기

  # logcat &

  # addserver03 &

7. client 실행하기

  # sqrtest3





Posted by '김용환'
,

안드로이드 플러그인이 설치된 이클립스에서 새로운 프로젝트를 생성한다.
Create proejcty from existing sample을 선택하면 Sample 컴보박스가 뜬다.





여기서 예제들을 선택하고 개념을 파악하면 쉽다.



Posted by '김용환'
,


1. 안드로이드 JNI 로그 남기기

이클립스의 LogCat 에서 jni가 출력되는 것을 보고 싶을 때 유용한다.
jni의 native단에서 printf로 출력되는 것은 adb shell로만 볼 수 있다.


Android.mk에 다음을 추가한다.
LOCAL_LDLIBS := -llog

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := test
LOCAL_SRC_FILES := test.c
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)






C 코드에 다음을 추가한다.

#include <android/log.h>

__android_log_print(ANDROID_LOG_DEBUG, "Tag_Name", "Message...");

레벨은 많다.
ANDROID_LOG_UNKNOWN
ANDROID_LOG_DEFAULT
ANDROID_LOG_VERBOSE
ANDROID_LOG_DEBUG
ANDROID_LOG_INFO
ANDROID_LOG_WARN
ANDROID_LOG_ERROR
ANDROID_LOG_FATAL
ANDROID_LOG_SILENT




#include <jni.h>
#include <android/log.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_google_AddJniActivity_addJNI
  (JNIEnv *env, jobject thiz, jint num1, jint num2)
{
        __android_log_print(ANDROID_LOG_ERROR, "GOOGLE", "******Message...");
         return num1+num2;
}

#ifdef __cplusplus
}
#endif




logcat에 에러가 남는다.




2. 두 개의 모듈을 컴파일 해보기


java  ==  jni-c  이런 상황에서 jni-c 파일이 사용하는 라이브러리가 따로 있는 경우를 의미한다.
즉 jni에서 명시적으로 가지고 쓰는 경우를 의미한다.


first.h

#ifndef FIRST_H
#define FIRST_H

extern int first(int  x, int  y);

#endif /* FIRST_H */




first.c

#include <android/log.h>

int  first(int  x, int  y)
{
 __android_log_print(ANDROID_LOG_DEBUG, "google", "** first.c, first function ");
     return x + y;
}






jni 코드 : test.c

#include <jni.h>
#include <android/log.h>
#include "first.h"

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_google_TwoLibs
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_google_TwoLibs_add
  (JNIEnv *env, jobject thiz, jint x, jint y) {
 __android_log_print(ANDROID_LOG_DEBUG, "google", "*******Message...");
   return first(x, y);
}

#ifdef __cplusplus
}
#endif





이런 경우의 android make 파일은 다음과 같이 지정한다.

Android.mk

LOCAL_PATH := $(call my-dir)

## 1st 다음은 libwolib-first 모듈를 만들자
include $(CLEAR_VARS)

LOCAL_MODULE    := libtwolib-first
LOCAL_SRC_FILES := first.c
LOCAL_LDLIBS := -llog

include $(BUILD_STATIC_LIBRARY)

## 2nd 다음은 libwolib-second 모듈을 만들자

include $(CLEAR_VARS)

LOCAL_MODULE    := libtwolib-second
LOCAL_SRC_FILES := second.c
LOCAL_LDLIBS := -llog

LOCAL_STATIC_LIBRARIES := libtwolib-first

include $(BUILD_SHARED_LIBRARY)



obj/local/armeabi 디렉토리 밑에 보면, first.a 파일과 secod.so 파일이 있는지 확인가능하다.
static lib는 linux archive를 의미한다.

$  ls -al
libtwolib-first.a
libtwolib-second.so
objs

libs/eabi 디렉토리는 static library를 포함하는 so 파일들이 만들어져 있다.
libs/eabi/libtwolib-second.so 파일을 이클립스 프로젝트에서 복사해서 사용한다.


3. module을 export 하기

여러 모듈(c, header) 파일이 있을 때, 여러개의 so파일과 함께 jni가 make 파일을 이용하여 프로그래밍을 할 수 있다.


foo.h

#ifndef FOO_H
#define FOO_H

extern int  foo(int x);

#endif /* FOO_H */




foo.c


#include "foo.h"
#include <android/log.h>

/* FOO should be defined to '2' when building foo.c */
#ifndef FOO
#error FOO is not defined here !
#endif

# android.mk 파일에서 설정값에 parameter값을 넣어서 동작되는 지를 확인하는 코드

#if FOO != 2
#error FOO is incorrectly defined here !
#endif

#define  LOG_TAG    "libfoo"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

int  foo(int  x)
{
    LOGI("foo(%d) called !", x);
    return x+1;
}





bar.h


#ifndef BAR_H
#define BAR_H

/* FOO should be defined to '1' here with the magic of LOCAL_EXPORT_CFLAGS */
#ifndef FOO
#error FOO should be defined here !
#endif

#if FOO != 1
#error FOO is not correctly defined here !
#endif

extern int  bar(int  x);

#endif /* BAR_H */





bar.c

#include "bar.h"
#include <android/log.h>

#define LOG_TAG  "libbar"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

int bar(int x)
{
 LOGI("bar(%d) called!!", x);
 return foo(x)-1;
}




zoo.c


#include "bar.h"
#include <android/log.h>

int something(void)
{
 __android_log_print(ANDROID_LOG_INFO, "libzoo", "something() called!!");
 return bar(42);
}




test.c

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_foo
  (JNIEnv *env, jobject thiz, jint val)
{
 return foo(val);
}

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_bar
  (JNIEnv *env, jobject thiz, jint val)
{
 return bar(val);
}

JNIEXPORT jint JNICALL Java_com_google_ModuleExports_zoo
  (JNIEnv *env, jobject thiz, jint val)
{
 return something();
}

#ifdef __cplusplus
}
#endif




java파일

class ActivityTest .... {

    public native int  foo(int val);
    public native int  bar(int val);
    public native int  zoo(int val);
   
    static {
        System.loadLibrary("bar");
        System.loadLibrary("zoo");
    }

}


Android.mk

LOCAL_PATH := $(call my-dir)

# FOO 값을 2로 만들어서  foo.c을 컴파일하고, FOO값을 1로 셋팅한후 archive 파일을 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_CFLAGS := -DFOO=2
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/foo
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

# bar.c 를 컴파일하고 static 파일이었던 foo.a 를 모아 bar.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar/bar.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

# zoo 파일을 jni파일인 test.c 파일과 함께 컴파일하고, zoo.so 파일로 만든다.
include $(CLEAR_VARS)
LOCAL_MODULE := zoo
LOCAL_SRC_FILES := test.c zoo/zoo.c
LOCAL_SHARED_LIBRARIES := bar
include $(BUILD_SHARED_LIBRARY)



../../ndk-build 결과는 다음과 같은 so 파일이 생성된다.






 

Posted by '김용환'
,

원래 root 패스워드를 알 수 없어서 . 변경한다. sudo 쓰기 진짜 귀찮다...

$ sudo passwd root
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Posted by '김용환'
,