Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1130282
  • 博文数量: 170
  • 博客积分: 1603
  • 博客等级: 上尉
  • 技术积分: 1897
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-09 15:54
文章分类

全部博文(170)

文章存档

2016年(27)

2015年(21)

2014年(27)

2013年(21)

2012年(7)

2011年(67)

我的朋友

分类: Android平台

2011-06-15 11:57:03

网上下的busybox多半是1.4的
新编译的BusyBox v1.18.4的多了不少命令,ash还能显示颜色,非常好用。

网上找到的dropbear是多半是0.4的,0.52那个交叉编译相关的文章里只有编译方法没有文件,而且patch也找不到了,找到的patch也不知道是不是对应0.52的,所以干脆根据patch对应修改编译最新版的dropbeadropbear-0.53.1
新版本dropbear只有一个单文件,和busybox一样做软连接ssh scp就可以了

=====================交叉编译工具工具========================

首先下载交叉编译工具
包选IA32 GNU/Linux TAR,我用的版本是arm-2011.03-41-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
这个是二进制包很方便,不用自己再编译交叉工具连了。
按习惯我解压丢到/usr/share下并把文件夹改名改名arm-android
结构如下
# ls /usr/share/arm-android
arm-none-linux-gnueabi  bin  lib  libexec  share


=======================busybox 1.18.4===============================
下载busybox,下最新版本的
我把要编译busybox的整个文件夹丢到/usr/src/android/下,现在进入busybox目录
# pwd
/usr/src/android/busybox-1.18.4
编译过程和下面网站说明基本一样除了路径
主要修改如下
make menuconfig
选择busybox se'ttings->General Configuration
[*] Don’t use /usr
这个选择上,选好后后退到上层目录
选择Build options
[*] Build BusyBox as a static binary,勾选这个静态模式编译,所有交叉编的程序译都要选这个
Cross Compiler prefex
这个里面就填写交叉编译其的gcc位置
因为Makefile里
 CC      = $(CROSS_COMPILE)gcc
所以这里的Cross Compiler prefex就是
/usr/share/arm-android/bin/arm-none-linux-gnueabi-
注意不要漏了"-" ,查看配置文件可以看到
cat .config | grep usr
CONFIG_CROSS_COMPILER_PREFIX="/usr/share/arm-android/bin/arm-none-linux-gnueabi-"
CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"

上面3个设置就可以了,不需要配置什么环境变量,当然你可以该下其他选项,可以减少busybox里包含的命令。
直接make就得到busybox的arm版了。

=============dropbear 的分割线===============

下面是dropbear。老版本的dropbear也可以用,但是我发现只能dropbear -v才能登入,这个模式不验证密码,pubkey又没办法验证,所以算是个挺有问题的版本。于是上网下载了最新版的dropbear自己编译。由于需要改动代码,我自己又是个半吊子都不算的连排序算法都忘记了的代码苦手,所以折腾了很久才搞定。

资料主要来源下面两个连接
这个连接应该是初始连接,但是里面提到的patch文件找不到了。网上可以找到的关于dropbear打补丁的下载地址都是连接到这个网站

下面这个连接提供了patch文件内容,但是不知道dropbear版本,所以也不知道这个patch是不是上面连接用的,但是看patch应该就是上面那个,解决方法差不多,里面提到的LIBS=$(LTC) $(LTM) $(LIBZ) -lutil  -lcrypt很有用,因为我编译的时候报错crypt相关错误,加了-lcrypt就通过了

把这个patch复制下来,在对应修改新版dropbear,我会一一说明相关修改。
如果你需要编译dropbear,你不需要去网上翻资料也不用看我上面给出的两个连接直接看我下面的内容就好
别人patch文件还是要看的,下面是下载连接
先需要下载zlib-1.2.3.tar.gz 
这个东西是ssh压缩传输用的,如果没这个那么你的客户端需要在压缩里选"无"
编译zlib
直接修改Makefile,把下面三个改了
CC=/usr/share/arm-android/bin/arm-none-linux-gnueabi-gcc
prefix =/data/dropbear
SHELL=/system/bin/sh
make;make install
注意,这个东西不需要丢到手机里,这个只是dropbear编译的时候需要用到而已,编译完dropbear就可以丢掉了。

下面对应patch改dropbear的代码
drobear需要改代码最重要的原因在上面那个英文连接里说明了
android没有/etc/passwd文件导致获取uid,pass之类的都出问题
看common-session.c
pw = getpwnam(username);
if (!pw) {
        dropbear_log(LOG_WARNING,"error,getpwam,user default");
   return;
    }
    ses.authstate.pw_uid = pw->pw_uid;
    ses.authstate.pw_gid = pw->pw_gid;
    ses.authstate.pw_name = m_strdup(pw->pw_name);
    ses.authstate.pw_dir = m_strdup(pw->pw_dir);
    ses.authstate.pw_shell = m_strdup(pw->pw_shell);
    ses.authstate.pw_passwd = m_strdup(pw->pw_passwd);
}

红色部分是我加的,不打patch直接编译dropbear并在手机上启动,登陆的时候就能看到错误了(同时还报错”Login attempt for nonexistent user from“,这个在svr-auth.c里面)
可以知道pw=getpwnam(username);没有数值的。
直接运行ssh会报错,这个错误也是因为无法获取的本机帐户相关信息。
这些错误都是由
getpwuid,getpwnam这两个系统函数引起。
这个patch的做法就是自己重写了这2个函数,让dropbear不去调用系统的这两个函数。

#ifdef DEBUG_HACKCRYPT
struct passwd pass;

struct passwd* getpwuid(uid_t uid)
{
    TRACE(("entering fake-getpwuid"));
    pass.pw_name  = "root";
    pass.pw_dir   = "/data/dropbear";
    pass.pw_shell = "/system/bin/sh";
    pass.pw_passwd = DEBUG_HACKCRYPT;
    pass.pw_uid   = 0;
    pass.pw_gid   = 0;

    TRACE(("leaving fake-getpwuid"));
    return &pass;
}

struct passwd* getpwnam(const char *login)
{
    TRACE(("entering fake-getpwnam"));
    pass.pw_name  = m_strdup(login);
    pass.pw_uid   = 0;
    pass.pw_gid   = 0;
    pass.pw_dir   = "/data/dropbear";
    pass.pw_passwd = DEBUG_HACKCRYPT;
    pass.pw_shell = "/system/bin/sh";
    TRACE(("leaving fake-getpwnam"));
    return &pass;
}

#endif

可以看到定义了DEBUG_HACKCRYPT的情况下添加这两个函数来代替系统的函数,功能很明显了。
我们照样子在svr-auth.c里面添加,在第40行后面,即
static void send_msg_userauth_banner();
后面加上面代码就是

由于用户shell部分判断有问题(也是svr-auth.c)
就是309行的
while ((listshell = getusershell()) != NULL) 这里的判断失效导致我们没能goto goodshell,
但是shell其实还是对的,所以这里直接在
/* no matching shell */
endusershell();
前面加入goto goodshell;就可以了,代码如下
308     setusershell();
309     while ((listshell = getusershell()) != NULL) {
310         TRACE(("test shell is '%s'", listshell))
311         if (strcmp(listshell, usershell) == 0) {
312             /* have a match */
313             goto goodshell;
314         }
315     }
316 #if 1
317     goto goodshell;
318 #else
319 
320     /* no matching shell */
321     endusershell();
322     TRACE(("no matching shell"))

这样shell获取就正确了。


然后是密码验证问题,因为android根本没密码,上面的方法定义了pw在对比密码的时候也没用,patch的解决方法就是直接验证成功(你可以通过dropbear -s来禁止密码登陆,为了调试方便可以先开启密码)
修改svr-authpasswd.c,在m_free(password);后面直接 send_msg_userauth_success();,这样就不任何密码都通过验证了。
81     password = buf_getstring(ses.payload, &passwordlen);
 82 
 83     /* the first bytes of passwdcrypt are the salt */
 84     testcrypt = crypt((char*)password, passwdcrypt);
 85     m_burn(password, passwordlen);
 86     m_free(password);
 87 
 88 #if 1
 89 
 90     send_msg_userauth_success();
 91 
 92 #else
 93     if (strcmp(testcrypt, passwdcrypt) == 0) {
 94         /* successful authentication */
 95         dropbear_log(LOG_NOTICE,
 96                 "Password auth succeeded for '%s' from %s",
 97                 ses.authstate.pw_name,
 98                 svr_ses.addrstring);
 99         send_msg_userauth_success();
100     } else {
101         dropbear_log(LOG_WARNING,
102                 "Bad password attempt for '%s' from %s",
103                 ses.authstate.pw_name,
104                 svr_ses.addrstring);
105         send_msg_userauth_failure(0, 1);
106     }
107 
108 #endif

加了这个以后,启动dropbear就不需要验证密码登陆,调试完后,可以用dropbear -s启动禁止输入密码验证模式登陆


options.h这个文件不需要像原来的patch文件那样改动那么多地方,因为configure帮我们设置了不少地方所以不需要修改那么多地方,需要改动的主要是

注释掉一个启动模式,具体你可以在主文件svr-main.c里看到,这里选择了NON_INETD_MODE
* Both of these flags can be defined at once, don't compile without at least
* one of them. */
#define NON_INETD_MODE
//#define INETD_MODE

取消掉MOTD,这个是Whether to print the message of the day (MOTD). This doesn't add much code,写message的,手机里自然写的东西越少越好不要日志,取消
153 /* The MOTD file path */
154 //#ifndef MOTD_FILENAME
155 //#define MOTD_FILENAME "/etc/motd"
156 //#endif

你可以选择取消密码登陆模式,这样就没有也不用-s模式了,svr-authpasswd.c也不用改了。
167 //#define ENABLE_SVR_PASSWORD_AUTH

下面几个就不用说明了
 22 /* Default hostkey paths - these can be specified on the command line */
 23 #ifndef DSS_PRIV_FILENAME
 24 #define DSS_PRIV_FILENAME "/data/dropbear/dropbear_dss_host_key"
 25 #endif
 26 #ifndef RSA_PRIV_FILENAME
 27 #define RSA_PRIV_FILENAME "/data/dropbear/dropbear_rsa_host_key"
 28 #endif

232 #ifndef DROPBEAR_PIDFILE
233 #define DROPBEAR_PIDFILE "/data/dropbear/dropbear.pid"
234 #endif

245 #ifndef SFTPSERVER_PATH
246 #define SFTPSERVER_PATH "/system/bin/sftp-server"
247 #endif

251 #define _PATH_SSH_PROGRAM "/system/bin/ssh"

288 #define DEFAULT_PATH "/sbin:/system/bin:/system/sbin"

还有个文件sysoptions.h要修改
#define _PATH_CP "/bin/cp"
改成
#define _PATH_CP "/system/bin/cp"




debug.h 修改,放开DEBUG_HACKCRYPT(这里因为自定义的getpwuid,getpwnam函数包含在这个定义内,我也不知道别人patch为什么要让这两个自定义函数包含在这个内,所以照搬了)
80 #define DEBUG_HACKCRYPT "hL8nrFDt0aJ3E"

然后就可以开始编译dropbear了
./configure --prefix=/system/bin --with-zlib=/data/dropbear --host=arm --disable-utmp --disable-utmpx --disable-wtmp --disable-wtmpx --disable-loginfunc --disable-lastlog --disable-syslog CC=/usr/share/arm-android/bin/arm-none-linux-gnueabi-gcc

如果你没有zlib,那么需要--disable-zlib

然后手动修改Makefile
23 LIBS+=$(LTC) $(LTM) -lcrypt
红色为增加部分

最后make
make PROGRAMS="dropbear dbclient scp dropbearkey" MULTI=1 STATIC=1 SCPPROGRESS=1

只有一个文件dropbearmulti有用,和busybox一样,scp ssh dropbear做软连接就能用了。

dropbear 不包括sftp-server,要用openssh的sftp-server
直接去下载,提取里面的sftp-server放到/system/bin/里就是


我是用n45的上网(fedora 14)本编译的,两个编译都不会太花时间。


阅读(6668) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~