前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >2023-04-15:ffmpeg的filter_audio.c的功能是生成一个正弦波音频,然后通过简单的滤镜链,最后输出数据的MD5校验和。请用go语言改写。

2023-04-15:ffmpeg的filter_audio.c的功能是生成一个正弦波音频,然后通过简单的滤镜链,最后输出数据的MD5校验和。请用go语言改写。

原创
作者头像
福大大架构师每日一题
发布于 2023-04-15 12:29:35
发布于 2023-04-15 12:29:35
3700
举报

2023-04-15:ffmpeg的filter_audio.c的功能是生成一个正弦波音频,然后通过简单的滤镜链,最后输出数据的MD5校验和。请用go语言改写。

答案2023-04-15:

代码见github/moonfdd/ffmpeg-go库。

以下是通过 Go 语言重新实现 ffmpeg 的 filter_audio.c 功能的步骤:

  1. 导入必要的依赖包和定义常量和变量。
  2. 初始化 FFmpeg 库文件路径。
  3. 创建一个音频滤镜图,并将 abuffer、volume 和 aformat 滤镜连接起来。其中,abuffer 滤镜用于获取输入音频采样,volume 滤镜用于调节音频音量,aformat 滤镜用于设置输出音频格式。
  4. 创建输出音频流的 AVCodecContext 上下文,并设置相关属性。
  5. 使用 avcodec_find_encoder_by_name 函数查找 PCM S16LE 编码器,然后创建编码器的 AVCodec 上下文。
  6. 打开编码器并写入头部信息。
  7. 循环读取音频帧,将其发送到音频滤镜图进行处理。
  8. 从滤镜图中获取输出音频帧,并将其编码为 PCM S16LE 格式。
  9. 计算输出音频帧的 MD5 校验和,并将其打印到标准输出上。
  10. 释放资源,结束程序运行。

以上就是使用 Go 语言对 filter_audio.c 文件进行重新实现的步骤。

命令如下:

代码语言:shell
复制
go run ./examples/internalexamples/filter_audio/main.go 1

go代码如下:

代码语言:go
复制
package main

import (
	"fmt"
	"math"
	"os"
	"strconv"
	"unsafe"

	"github.com/moonfdd/ffmpeg-go/ffcommon"
	"github.com/moonfdd/ffmpeg-go/libavfilter"
	"github.com/moonfdd/ffmpeg-go/libavutil"
)

func main0() (ret ffcommon.FInt) {
	var md5 *libavutil.AVMD5
	var graph *libavfilter.AVFilterGraph
	var src, sink *libavfilter.AVFilterContext
	var frame *libavutil.AVFrame
	var errstr [1024]ffcommon.FUint8T
	var duration ffcommon.FFloat
	var err, nb_frames, i ffcommon.FInt

	if len(os.Args) < 2 {
		fmt.Printf("Usage: %s <duration>\n", os.Args[0])
		return 1
	}

	f, err2 := strconv.ParseFloat(os.Args[1], 32)
	if err2 != nil {
		// handle error
		return 1
	}
	duration = float32(f)
	nb_frames = int32(float64(duration) * INPUT_SAMPLERATE / FRAME_SIZE)
	if nb_frames <= 0 {
		fmt.Printf("Invalid duration: %s\n", os.Args[1])
		return 1
	}

	/* Allocate the frame we will be using to store the data. */
	frame = libavutil.AvFrameAlloc()
	if frame == nil {
		fmt.Printf("Error allocating the frame\n")
		return 1
	}

	md5 = libavutil.AvMd5Alloc()
	if md5 == nil {
		fmt.Printf("Error allocating the MD5 context\n")
		return 1
	}

	/* Set up the filtergraph. */
	err = init_filter_graph(&graph, &src, &sink)
	if err < 0 {
		fmt.Printf("Unable to init filter graph:")
		goto fail
	}

	/* the main filtering loop */
	for i = 0; i < nb_frames; i++ {
		// /* get an input frame to be filtered */
		err = get_input(frame, i)
		if err < 0 {
			fmt.Printf("Error generating input frame:")
			goto fail
		}

		/* Send the frame to the input of the filtergraph. */
		err = src.AvBuffersrcAddFrame(frame)
		if err < 0 {
			frame.AvFrameUnref()
			fmt.Printf("Error submitting the frame to the filtergraph:")
			goto fail
		}

		/* Get all the filtered output that is available. */
		err = sink.AvBuffersinkGetFrame(frame)
		for err >= 0 {
			/* now do something with our filtered frame */
			err = process_output(md5, frame)
			if err < 0 {
				fmt.Printf("Error processing the filtered frame:")
				goto fail
			}
			frame.AvFrameUnref()
			err = sink.AvBuffersinkGetFrame(frame)
		}

		if err == -libavutil.EAGAIN {
			/* Need to feed more frames in. */
			continue
		} else if err == libavutil.AVERROR_EOF {
			/* Nothing more to do, finish. */
			break
		} else if err < 0 {
			/* An error occurred. */
			fmt.Printf("Error filtering the data:")
			goto fail
		}
	}

	libavfilter.AvfilterGraphFree(&graph)
	libavutil.AvFrameFree(&frame)
	libavutil.AvFreep(uintptr(unsafe.Pointer(&md5)))

	return 0

fail:
	libavutil.AvStrerror(err, (*byte)(unsafe.Pointer(&errstr)), uint64(len(errstr)))
	fmt.Printf("%s\n", errstr)
	return 1
}

const INPUT_SAMPLERATE = 48000
const INPUT_FORMAT = libavutil.AV_SAMPLE_FMT_FLTP
const INPUT_CHANNEL_LAYOUT = libavutil.AV_CH_LAYOUT_5POINT0

const VOLUME_VAL = 0.90

func init_filter_graph(graph **libavfilter.AVFilterGraph, src **libavfilter.AVFilterContext,
	sink **libavfilter.AVFilterContext) ffcommon.FInt {
	var filter_graph *libavfilter.AVFilterGraph
	var abuffer_ctx *libavfilter.AVFilterContext
	var abuffer *libavfilter.AVFilter
	var volume_ctx *libavfilter.AVFilterContext
	var volume *libavfilter.AVFilter
	var aformat_ctx *libavfilter.AVFilterContext
	var aformat *libavfilter.AVFilter
	var abuffersink_ctx *libavfilter.AVFilterContext
	var abuffersink *libavfilter.AVFilter

	var options_dict *libavutil.AVDictionary
	var options_str string
	var ch_layout [64]ffcommon.FUint8T

	var err ffcommon.FInt

	/* Create a new filtergraph, which will contain all the filters. */
	filter_graph = libavfilter.AvfilterGraphAlloc()
	if filter_graph == nil {
		fmt.Printf("Unable to create filter graph.\n")
		return libavutil.ENOMEM
	}

	/* Create the abuffer filter;
	 * it will be used for feeding the data into the graph. */
	abuffer = libavfilter.AvfilterGetByName("abuffer")
	if abuffer == nil {
		fmt.Printf("Could not find the abuffer filter.\n")
		return libavutil.AVERROR_FILTER_NOT_FOUND
	}

	abuffer_ctx = filter_graph.AvfilterGraphAllocFilter(abuffer, "src")
	if abuffer_ctx == nil {
		fmt.Printf("Could not allocate the abuffer instance.\n")
		return -libavutil.ENOMEM
	}

	/* Set the filter options through the AVOptions API. */
	libavutil.AvGetChannelLayoutString((*byte)(unsafe.Pointer(&ch_layout)), int32(len(ch_layout)), 0, INPUT_CHANNEL_LAYOUT)
	libavutil.AvOptSet(uintptr(unsafe.Pointer(abuffer_ctx)), "channel_layout", ffcommon.StringFromPtr(uintptr(unsafe.Pointer(&ch_layout))), libavutil.AV_OPT_SEARCH_CHILDREN)
	libavutil.AvOptSet(uintptr(unsafe.Pointer(abuffer_ctx)), "sample_fmt", libavutil.AvGetSampleFmtName(INPUT_FORMAT), libavutil.AV_OPT_SEARCH_CHILDREN)
	libavutil.AvOptSetQ(uintptr(unsafe.Pointer(abuffer_ctx)), "time_base", libavutil.AVRational{1, INPUT_SAMPLERATE}, libavutil.AV_OPT_SEARCH_CHILDREN)
	libavutil.AvOptSetInt(uintptr(unsafe.Pointer(abuffer_ctx)), "sample_rate", INPUT_SAMPLERATE, libavutil.AV_OPT_SEARCH_CHILDREN)

	/* Now initialize the filter; we pass NULL options, since we have already
	 * set all the options above. */
	err = abuffer_ctx.AvfilterInitStr("")
	if err < 0 {
		fmt.Printf("Could not initialize the abuffer filter.\n")
		return err
	}

	/* Create volume filter. */
	volume = libavfilter.AvfilterGetByName("volume")
	if volume == nil {
		fmt.Printf("Could not find the volume filter.\n")
		return libavutil.AVERROR_FILTER_NOT_FOUND
	}

	volume_ctx = filter_graph.AvfilterGraphAllocFilter(volume, "volume")
	if volume_ctx == nil {
		fmt.Printf("Could not allocate the volume instance.\n")
		return -libavutil.ENOMEM
	}

	/* A different way of passing the options is as key/value pairs in a
	 * dictionary. */
	libavutil.AvDictSet(&options_dict, "volume", fmt.Sprint(VOLUME_VAL), 0)
	err = volume_ctx.AvfilterInitDict(&options_dict)
	libavutil.AvDictFree(&options_dict)
	if err < 0 {
		fmt.Printf("Could not initialize the volume filter.\n")
		return err
	}

	/* Create the aformat filter;
	 * it ensures that the output is of the format we want. */
	aformat = libavfilter.AvfilterGetByName("aformat")
	if aformat == nil {
		fmt.Printf("Could not find the aformat filter.\n")
		return libavutil.AVERROR_FILTER_NOT_FOUND
	}

	aformat_ctx = filter_graph.AvfilterGraphAllocFilter(aformat, "aformat")
	if aformat_ctx == nil {
		fmt.Printf("Could not allocate the aformat instance.\n")
		return -libavutil.ENOMEM
	}

	/* A third way of passing the options is in a string of the form
	 * key1=value1:key2=value2.... */
	// snprintf(options_str, sizeof(options_str),
	//          "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64,
	//          av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100,
	//          (uint64_t)AV_CH_LAYOUT_STEREO);
	options_str = fmt.Sprintf("sample_fmts=%s:sample_rates=%d:channel_layouts=0x%x",
		libavutil.AvGetSampleFmtName(libavutil.AV_SAMPLE_FMT_S16), 44100,
		libavutil.AV_CH_LAYOUT_STEREO)
	fmt.Println(options_str)
	err = aformat_ctx.AvfilterInitStr(options_str)
	if err < 0 {
		libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Could not initialize the aformat filter.\n")
		return err
	}

	/* Finally create the abuffersink filter;
	 * it will be used to get the filtered data out of the graph. */
	abuffersink = libavfilter.AvfilterGetByName("abuffersink")
	if abuffersink == nil {
		fmt.Printf("Could not find the abuffersink filter.\n")
		return libavutil.AVERROR_FILTER_NOT_FOUND
	}

	abuffersink_ctx = filter_graph.AvfilterGraphAllocFilter(abuffersink, "sink")
	if abuffersink_ctx == nil {
		fmt.Printf("Could not allocate the abuffersink instance.\n")
		return -libavutil.ENOMEM
	}

	/* This filter takes no options. */
	err = abuffersink_ctx.AvfilterInitStr("")
	if err < 0 {
		fmt.Printf("Could not initialize the abuffersink instance.\n")
		return err
	}

	/* Connect the filters;
	 * in this simple case the filters just form a linear chain. */
	err = abuffer_ctx.AvfilterLink(0, volume_ctx, 0)
	if err >= 0 {
		err = volume_ctx.AvfilterLink(0, aformat_ctx, 0)
	}
	if err >= 0 {
		err = aformat_ctx.AvfilterLink(0, abuffersink_ctx, 0)
	}
	if err < 0 {
		fmt.Printf("Error connecting filters\n")
		return err
	}

	/* Configure the graph. */
	err = filter_graph.AvfilterGraphConfig(uintptr(0))
	if err < 0 {
		libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Error configuring the filter graph\n")
		return err
	}

	*graph = filter_graph
	*src = abuffer_ctx
	*sink = abuffersink_ctx

	return 0
}

/* Do something useful with the filtered data: this simple
 * example just prints the MD5 checksum of each plane to stdout. */
func process_output(md5 *libavutil.AVMD5, frame *libavutil.AVFrame) ffcommon.FInt {
	planar := libavutil.AvSampleFmtIsPlanar(libavutil.AVSampleFormat(frame.Format))
	channels := libavutil.AvGetChannelLayoutNbChannels(frame.ChannelLayout)
	planes := channels
	if planar == 0 {
		planes = 1
	}
	bps := libavutil.AvGetBytesPerSample(libavutil.AVSampleFormat(frame.Format))
	plane_size := bps * frame.NbSamples
	if planar == 0 {
		plane_size = plane_size * channels
	}
	var i, j ffcommon.FInt

	for i = 0; i < planes; i++ {
		var checksum [16]ffcommon.FUint8T

		md5.AvMd5Init()
		ptr := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(frame.ExtendedData)) + uintptr(i*8)))
		libavutil.AvMd5Sum((*byte)(unsafe.Pointer(&checksum)), (*byte)(unsafe.Pointer(ptr)), plane_size)

		fmt.Printf("plane %d: 0x", i)
		for j = 0; j < int32(len(checksum)); j++ {
			fmt.Printf("%02X", checksum[j])
		}
		fmt.Printf("\n")
	}
	fmt.Printf("\n")

	return 0
}

const FRAME_SIZE = 1024

/* Construct a frame of audio data to be filtered;
 * this simple example just synthesizes a sine wave. */
func get_input(frame *libavutil.AVFrame, frame_num ffcommon.FInt) ffcommon.FInt {
	var err, i, j ffcommon.FInt

	// #define FRAME_SIZE 1024

	/* Set up the frame properties and allocate the buffer for the data. */
	frame.SampleRate = INPUT_SAMPLERATE
	frame.Format = INPUT_FORMAT
	frame.ChannelLayout = INPUT_CHANNEL_LAYOUT
	frame.NbSamples = FRAME_SIZE
	frame.Pts = int64(frame_num) * FRAME_SIZE

	err = frame.AvFrameGetBuffer(0)
	if err < 0 {
		return err
	}

	/* Fill the data for each channel. */
	for i = 0; i < 5; i++ {
		// float *data = (float*)frame->extended_data[i];
		ptr := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(frame.ExtendedData)) + uintptr(i*8)))
		data := (*ffcommon.FFloat)(unsafe.Pointer(ptr))

		for j = 0; j < frame.NbSamples; j++ {
			*(*ffcommon.FFloat)(unsafe.Pointer(uintptr(unsafe.Pointer(data)) + uintptr(4*j))) = float32(math.Sin(2 * libavutil.M_PI * (float64(frame_num + j)) * float64((i+1)/FRAME_SIZE)))
		}
	}

	return 0
}

func main() {
	// go run ./examples/internalexamples/filter_audio/main.go 1
	os.Setenv("Path", os.Getenv("Path")+";./lib")
	ffcommon.SetAvutilPath("./lib/avutil-56.dll")
	ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")
	ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")
	ffcommon.SetAvfilterPath("./lib/avfilter-7.dll")
	ffcommon.SetAvformatPath("./lib/avformat-58.dll")
	ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")
	ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")
	ffcommon.SetAvswscalePath("./lib/swscale-5.dll")

	genDir := "./out"
	_, err := os.Stat(genDir)
	if err != nil {
		if os.IsNotExist(err) {
			os.Mkdir(genDir, 0777) //  Everyone can read write and execute
		}
	}

	main0()
}

运行结果如下:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
android 壳特征
类加载技术: 针对apk中的classes.dex文件进行处理,放入待定的文件中,通过native代码来进行对其运行时解密。
tea9
2022/09/08
1.2K0
android 壳特征
app加固_360加固保手机版
答:因为黑客通过反编译APK得到源码后,会在应用中插入代码,获取利益,比如添加广告,盗取用户账号、密码,后台定制活动等。
全栈程序员站长
2022/09/20
6.3K0
CTF逆向指南
在CTF比赛中, CTF逆向题目除了需要分析程序工作原理, 还要根据分析结果进一步求出FLAG。逆向在解题赛制中单独占一类题型, 同时也是PWN题的前置技能。在攻防赛制中常与PWN题结合。CTF逆向主要涉及到逆向分析和破解技巧,这也要求有较强的反汇编、反编译、加解密的功底。
小道安全
2021/09/24
2.1K0
CTF逆向指南
提高APP安全性的必备加固手段——深度解析代码混淆技术
iOSAPP 加固是优化 APK 安全性的一种方法,常见的加固方式有混淆代码、加壳、数据加密、动态加载等。下面介绍一下 iOSAPP 加固的具体实现方式。
iOS Magician
2023/11/17
5140
提高APP安全性的必备加固手段——深度解析代码混淆技术
安卓 APP 三代加壳方案的研究报告
a、原理很简单,就是首先将我们的 dex 文件或者 apk 文件解密,然后利用DexClassLoader加载器将其加载进内存中,然后利用反射加载待加固的 apk 的 appkication,然后运行待加固程序即可,我画了个流程图详细说明如下:
信安之路
2020/09/11
4K0
【Android 逆向】加壳技术简介 ( 动态加载 | 第一代加壳技术 - DEX 整体加固 | 第二代加壳技术 - 函数抽取 | 第三代加壳技术 - VMP / Dex2C | 动态库加壳技术 )
动态加载 : 调用 Java 类时 , 使用到的时候 , 才从 DEX 字节码文件中加载对应的字节码类 ;
韩曙亮
2023/03/30
1.7K0
爱加密企业版静态脱壳机编写
加壳时将方法指令抽走后自定义格式加密存放在assets/ijiami.ajm文件中,通过IDA动态调试分析发现每个被抽走的方法的debuginfo值改成0X3F开始的8字节大不的值,该值在还原时做为Map的KEY。
我是小三
2018/08/08
4.2K0
爱加密企业版静态脱壳机编写
ApkScan-PKID 查壳工具下载使用以及相关技术介绍
1、壳的功能:壳最本质的功能就是实现加载器,壳是指在一个程序的外面再包裹上另外一段代码,保护里面的代码不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务,深入点就是在apk外面再套一层壳,在运行的时候这层壳会把真正的apk的dalvik指令集释放出来,为apk加壳是目前主流的防护方案,真正的源码是隐藏在壳之下的,要想拿到源码研究其逻辑就要先想办法将壳脱掉,所以我们拿到一个apk要逆向的第一步就是用查壳工具看下这个apk文件是否加壳,以及加了什么壳,然后想办法把壳脱掉,拿到dex文件再去分析。 注意:壳绝对不能改变原来代码的执行流程;加壳程序也不能对源程序有任何的影响。 2、apk的组成原理:apk壳和pc端的都差不多,只是在处理不同的文件格式dex和exe中会有差别;导致不同的加壳;Android上的应用安装文件是apk格式的,这个apk文件其实就是个归档文件压缩包,把应用相关的源码、资源文件、配置文件等等都归档打包,直接解压之后就能得到app的dalvik指令集dex文件,然后再反编译为smali,还可以再反编译为Java,这样就几乎等同于拿到了app就能拿到可读性还蛮清晰的源码。 3、Android Dex文件加壳原理:Android APK加壳过程中,牵扯到三个角色:加壳程序(加密源程序为解壳数据、组装解壳程序和解壳数据)、解壳程序(解密解壳数据,并运行时通过DexClassLoader动态加载)、(源程序)需要加壳处理的被保护代码
EXI-小洲
2022/12/13
4.5K0
ApkScan-PKID 查壳工具下载使用以及相关技术介绍
浅谈安卓apk加固原理和实现
在安卓开发中,打包发布是开发的最后一个环节,apk是整个项目的源码和资源的结合体;对于懂点反编译原理的人可以轻松编译出apk的源码资源,并且可以修改资源代码、重新打包编译,轻轻松松变成自己的apk或者修改其中一部分窃取用户信息。
yuanyi928
2018/12/24
3.8K0
浅谈安卓apk加固原理和实现
[1198]ApkScan-PKID 查壳工具
1、壳的功能:壳最本质的功能就是实现加载器,壳是指在一个程序的外面再包裹上另外一段代码,保护里面的代码不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务,深入点就是在apk外面再套一层壳,在运行的时候这层壳会把真正的apk的dalvik指令集释放出来,为apk加壳是目前主流的防护方案,真正的源码是隐藏在壳之下的,要想拿到源码研究其逻辑就要先想办法将壳脱掉,所以我们拿到一个apk要逆向的第一步就是用查壳工具看下这个apk文件是否加壳,以及加了什么壳,然后想办法把壳脱掉,拿到dex文件再去分析。
周小董
2023/10/10
6940
[1198]ApkScan-PKID 查壳工具
APP爬虫技术总结
d.通过写xposed hook插件打印请求url和请求参数(示例可参照下面的案例)
全栈程序员站长
2022/08/26
6730
APP爬虫技术总结
android apk 防反编译技术第一篇-加壳技术
做android framework方面的工作将近三年的时间了,现在公司让做一下android apk安全方面的研究,于是最近就在网上找大量的资料来学习。现在将最近学习成果做一下整理总结。学习的这些成果我会做成一个系列慢慢写出来与大家分享,共同进步。这篇主要讲apk的加壳技术,废话不多说了直接进入正题。 一、加壳技术原理 所谓apk的加壳技术和pc exe的加壳原理一样,就是在程序的外面再包裹上另外一段代码,保护里面的代码不被非法修改或反编译,在程序运行的时候优先取得程序的控制权做一些我们自己想做的工作
程序员互动联盟
2018/03/12
2.4K0
android apk 防反编译技术第一篇-加壳技术
【胖虎的逆向之路】02——Android整体加壳原理详解&实现
为了深入了解Android 逆向相关的内容中加壳的原理,前面已经完成了关于Android中的动态加载和动态加载类关系的详解,那么接下来是对Android的整体加壳进行实现,并对原理进行讲解,由于作者能力有限,会尽力的详细描述整体加壳的流程及原理,如本文中有任何错误,烦请指正,感谢~
胖虎哥
2023/05/10
7880
【胖虎的逆向之路】02——Android整体加壳原理详解&实现
APP加固攻防梳理
现在市面上对APP的安全合规管控越来越严格了,也就要求了APP在上架之前一定要做合规检测和加固处理。对APP就是加固的好处,可以提高APP的安全性,提高APP被逆向分析破解的门槛,同时通过加固保护可以提高过安全合规的检测。由于APP加固技术不断被攻破情况,因此加固技术也是不断在快速迭代的过程。现在市面上的加固产品的还是比较多的,并且各个加固技术产品都有其各自优缺点,但是加固产品的所采用技术去有很多共性的地方。下面就对加固和脱壳对抗方案做些梳理总结。
小道安全
2021/10/14
3.1K1
APP加固攻防梳理
某移动应用安全加固与脱壳技术研究与实例分析
01 概述 — 由于近期很多朋友问关于Android加壳与脱壳技术,这两天我就对目前主流的脱壳工具和加壳方法做了研究,就对目前的脱壳方法做个汇总和方法记录。 首先目前市面上有很多的安卓脱壳工具,主流的有DexExtractor, ZjDroid, drizzleDumper,其中前面的2个工具与后面的工具略有不同,文章会一一对工具进行分析和尝试脱壳,各个工具的使用都在手机root的环境下进行的,并且在实体机上进行,所以如果有读者尝试破解的话建议还是在实体机上进行。 其实对于加壳的方案很多加固尝试都做了什么
xfkxfk
2018/05/15
3.2K0
[1197]脱壳工具dumpDex的使用详解
dumpDex: 一个开源的 Android 脱壳插件工具,需要xposed支持。可以用来脱掉当前市场上大部分的壳。(360加固、腾讯乐固、梆梆加固、百度加固均可脱壳)
周小董
2023/10/10
4.1K0
Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
iOS程序应用
2023/11/23
9360
android 常用加密,分享一下Android各种类型的加密
几维安全com.Kiwisec.KiwiSecApplication或者com.Kiwisec.ProxyApplication或者干脆没有application
全栈程序员站长
2022/08/29
7860
【Android 逆向】加壳技术识别 ( VMP 加壳示例 | Dex2C 加壳示例 )
加壳技术识别的必要性 : 拿到 APK 文件后 , 如果想要分析其 DEX 文件 , 需要先 识别出该 APK 是使用的什么技术进行的加壳 , 如果该 APK 只是使用了整体保护 , 只需要将内存中的 DEX 文件 DUMP 下来即可 ; 如果该 APK 使用了 VMP 加壳 , 则需要逆向分析解释器 ;
韩曙亮
2023/03/30
5.8K0
面试题丨android面试问题合集
静态分析工具是指在不运行程序的情况下,通过对程序文件进行源代码分析,从而对程序的安全性、可靠性、性能等进行分析的工具。它可以识别出程序文件中的漏洞,但只能识别出程序文件中的静态漏洞,不能识别出程序在运行中可能出现的动态漏洞。比如apktool、androidkiller、jeb,GDA、smali、jadx等
极安御信安全研究院
2023/06/08
2.3K1
面试题丨android面试问题合集
推荐阅读
相关推荐
android 壳特征
更多 >
目录
  • 以下是通过 Go 语言重新实现 ffmpeg 的 filter_audio.c 功能的步骤:
  • 命令如下:
  • go代码如下:
  • 运行结果如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档