diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
index 812411c04..2410a8ef9 100644
--- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
+++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
@@ -25,12 +25,12 @@ data class QQDTO(
 @Serializable
 data class MemberDTO(
     override val id: Long,
-    val memberName: String = "",
+    val memberName: String,
     val permission: MemberPermission,
     val group: GroupDTO
 ) : ContactDTO() {
-    constructor(member: Member, name: String = "") : this (
-        member.id, name, member.permission, GroupDTO(member.group)
+    constructor(member: Member) : this (
+        member.id, member.groupCard, member.permission, GroupDTO(member.group)
     )
 }
 
diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
index 13b14b05b..e670b3f33 100644
--- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
+++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
@@ -31,13 +31,13 @@ data class UnKnownMessagePacketDTO(val msg: String) : MessagePacketDTO()
 data class AtDTO(val target: Long, val display: String) : MessageDTO()
 @Serializable
 @SerialName("Face")
-data class FaceDTO(val faceID: Int) : MessageDTO()
+data class FaceDTO(val faceId: Int) : MessageDTO()
 @Serializable
 @SerialName("Plain")
 data class PlainDTO(val text: String) : MessageDTO()
 @Serializable
 @SerialName("Image")
-data class ImageDTO(val path: String) : MessageDTO()
+data class ImageDTO(val imageId: String) : MessageDTO()
 @Serializable
 @SerialName("Xml")
 data class XmlDTO(val xml: String) : MessageDTO()
@@ -64,7 +64,7 @@ sealed class MessageDTO : DTO
  */
 suspend fun MessagePacket<*, *>.toDTO(): MessagePacketDTO = when (this) {
     is FriendMessage -> FriendMessagePacketDTO(QQDTO(sender))
-    is GroupMessage -> GroupMessagePacketDTO(MemberDTO(sender, senderName))
+    is GroupMessage -> GroupMessagePacketDTO(MemberDTO(sender))
     else -> UnKnownMessagePacketDTO("UnKnown Message Packet")
 }.apply { messageChain = Array(message.size){ message[it].toDTO() }}
 
@@ -76,7 +76,7 @@ fun Message.toDTO() = when (this) {
     is At -> AtDTO(target, display)
     is Face -> FaceDTO(id.value.toInt())
     is PlainText -> PlainDTO(stringValue)
-    is Image -> ImageDTO(this.toString())
+    is Image -> ImageDTO(imageId)
     is XMLMessage -> XmlDTO(stringValue)
     else -> UnknownMessageDTO("未知消息类型")
 }
@@ -84,9 +84,9 @@ fun Message.toDTO() = when (this) {
 @UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
 fun MessageDTO.toMessage() = when (this) {
     is AtDTO -> At(target, display)
-    is FaceDTO -> Face(FaceId(faceID.toUByte()))
+    is FaceDTO -> Face(FaceId(faceId.toUByte()))
     is PlainDTO -> PlainText(text)
-    is ImageDTO -> PlainText("[暂时不支持图片]")
+    is ImageDTO -> Image(imageId)
     is XmlDTO -> XMLMessage(xml)
     is UnknownMessageDTO -> PlainText("assert cannot reach")
 }
diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
index 4437083f2..e652c5167 100644
--- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
+++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
@@ -4,6 +4,7 @@ import kotlinx.serialization.Serializable
 import kotlinx.serialization.Transient
 import net.mamoe.mirai.api.http.AuthedSession
 import net.mamoe.mirai.contact.Group
+import net.mamoe.mirai.contact.Member
 
 @Serializable
 abstract class VerifyDTO : DTO {
@@ -60,6 +61,22 @@ data class GroupInfoDTO(
     )
 }
 
+@Serializable
+data class MemberConfigDTO(
+    override val sessionKey: String,
+    val target: Long,
+    val memberId: Long,
+    val config: MemberInfoDTO
+) : VerifyDTO()
+
+@Serializable
+data class MemberInfoDTO(
+    val name: String? = null,
+    val specialTitle: String? = null
+) : DTO {
+    constructor(member: Member) : this(member.groupCard, member.specialTitle)
+}
+
 @Serializable
 open class StateCode(val code: Int, var msg: String) {
     object Success : StateCode(0, "success") // 成功
diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt
index d97c27ac7..69299ae06 100644
--- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt
+++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt
@@ -3,17 +3,14 @@ package net.mamoe.mirai.api.http.route
 import io.ktor.application.Application
 import io.ktor.application.call
 import io.ktor.routing.routing
-import net.mamoe.mirai.api.http.dto.GroupConfigDTO
-import net.mamoe.mirai.api.http.dto.GroupInfoDTO
-import net.mamoe.mirai.api.http.dto.MuteDTO
-import net.mamoe.mirai.api.http.dto.StateCode
+import net.mamoe.mirai.api.http.dto.*
 
 
 fun Application.groupManageModule() {
     routing {
 
         /**
-         * 禁言
+         * 禁言(需要相关权限)
          */
         miraiVerify<MuteDTO>("/muteAll") {
             it.session.bot.getGroup(it.target).muteAll = true
@@ -61,5 +58,22 @@ fun Application.groupManageModule() {
             call.respondStateCode(StateCode.Success)
         }
 
+        /**
+         * 群员信息管理(需要相关权限)
+         */
+        miraiGet("/memberInfo") {
+            val member = it.bot.getGroup(paramOrNull("target"))[paramOrNull("memberID")]
+            call.respondDTO(MemberInfoDTO(member))
+        }
+
+        miraiVerify<MemberConfigDTO>("/memberInfo") { dto ->
+            val member = dto.session.bot.getGroup(dto.target)[dto.memberId]
+            with(dto.config) {
+                name?.let { member.groupCard = it }
+                specialTitle?.let { member.specialTitle = it }
+            }
+            call.respondStateCode(StateCode.Success)
+        }
+
     }
 }
\ No newline at end of file
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
index 9c891a3c7..0992d648b 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
@@ -64,14 +64,14 @@ private fun calculateImageMd5ByImageId(imageId: String): ByteArray {
     return if (imageId.startsWith('/')) {
         imageId
             .drop(1)
-            .replace('-', ' ')
+            .replace("-", "")
             .take(16 * 2)
             .chunkedHexToBytes()
     } else {
         imageId
             .substringAfter('{')
             .substringBefore('}')
-            .replace('-', ' ')
+            .replace("-", "")
             .chunkedHexToBytes()
     }
 }